├── restore-packages.cmd
├── language-extensions
├── dotnet-core-CSharp
│ ├── lib
│ │ └── hostfxr.dll
│ ├── sample
│ │ ├── regex
│ │ │ ├── RegexSampleResult.PNG
│ │ │ ├── pkg
│ │ │ │ ├── RegexSample.csproj
│ │ │ │ └── RegexSample.cs
│ │ │ └── dotnet-core-CSharp-regex-win.sql
│ │ ├── SubModuleCall
│ │ │ └── SubModuleProject
│ │ │ │ └── SubModule
│ │ │ │ ├── SubModule.csproj
│ │ │ │ ├── SubModule.sln
│ │ │ │ └── Program.cs
│ │ └── LoopBackConnection
│ │ │ ├── README.md
│ │ │ └── LoopBackConnectionOLEDB.cs
│ ├── build
│ │ └── windows
│ │ │ ├── restore-packages.cmd
│ │ │ └── create-dotnet-core-CSharp-extension-zip.cmd
│ ├── src
│ │ ├── managed
│ │ │ ├── Microsoft.SqlServer.CSharpExtension.csproj
│ │ │ ├── utils
│ │ │ │ ├── ExceptionUtils.cs
│ │ │ │ └── DataSetUtils.cs
│ │ │ ├── CSharpDataSet.cs
│ │ │ ├── CSharpColumn.cs
│ │ │ ├── sdk
│ │ │ │ └── AbstractSqlServerExtensionExecutor.cs
│ │ │ └── CSharpParam.cs
│ │ └── native
│ │ │ └── Logger.cpp
│ ├── test
│ │ ├── include
│ │ │ └── Common.h
│ │ ├── src
│ │ │ ├── managed
│ │ │ │ └── Microsoft.SqlServer.CSharpExtensionTest.csproj
│ │ │ └── native
│ │ │ │ ├── main.cpp
│ │ │ │ ├── CSharpInitSessionTests.cpp
│ │ │ │ └── CMakeLists.txt
│ │ └── build
│ │ │ └── windows
│ │ │ └── run-dotnet-core-CSharp-extension-test.cmd
│ ├── include
│ │ ├── Logger.h
│ │ ├── coreclr_delegates.h
│ │ └── hostfxr.h
│ └── LICENSE
├── python
│ ├── test
│ │ ├── test_packages
│ │ │ ├── astor.whl
│ │ │ ├── astor-0.7.1-WHL.zip
│ │ │ ├── bad-package-ZIP.zip
│ │ │ ├── statsd-3.3.0-WHL.zip
│ │ │ ├── testpackageA-ZIP.zip
│ │ │ ├── testpackageB-ZIP.zip
│ │ │ ├── testpackageC-ZIP.zip
│ │ │ ├── absl-py-1.0.0-TAR.zip
│ │ │ ├── testpackagebad-ZIP.zip
│ │ │ ├── Markdown-2.6.11-ZIP.zip
│ │ │ ├── telemetry-0.3.2-TAR.zip
│ │ │ ├── termcolor-1.1.0-TAR.zip
│ │ │ └── testpackageA-v2-ZIP.zip
│ │ ├── include
│ │ │ ├── Common.h
│ │ │ ├── PythonTestUtilities.h
│ │ │ └── PythonLibraryTests.h
│ │ ├── src
│ │ │ ├── main.cpp
│ │ │ ├── PythonInitTests.cpp
│ │ │ └── PythonInitColumnTests.cpp
│ │ └── build
│ │ │ ├── windows
│ │ │ └── run-pythonextension-test.cmd
│ │ │ └── linux
│ │ │ └── run-pythonextension-test.sh
│ ├── include
│ │ ├── Common.h
│ │ ├── Logger.h
│ │ ├── PythonColumn.h
│ │ ├── PythonNamespace.h
│ │ ├── PythonPathSettings.h
│ │ ├── PythonExtensionUtils.h
│ │ └── PythonLibrarySession.h
│ ├── build
│ │ ├── linux
│ │ │ ├── create-python-extension-zip.sh
│ │ │ └── restore-packages.sh
│ │ └── windows
│ │ │ └── create-python-extension-zip.cmd
│ ├── LICENSE_1_0.txt
│ └── src
│ │ ├── PythonColumn.cpp
│ │ ├── PythonPathSettings.cpp
│ │ ├── Logger.cpp
│ │ ├── PythonNamespace.cpp
│ │ └── linux
│ │ └── PythonExtensionUtils_linux.cpp
├── R
│ ├── test
│ │ ├── test-packages
│ │ │ ├── linux
│ │ │ │ ├── 1_1_bindr_0.1.1.zip
│ │ │ │ ├── 1_1_plogr_0.2.0.zip
│ │ │ │ ├── 24_58_rlang_1.1.6.zip
│ │ │ │ ├── 1_1_assertthat_0.2.1.zip
│ │ │ │ ├── 1_1_lazyeval_0.2.2.zip
│ │ │ │ ├── 1_1_pkgconfig_2.0.3.zip
│ │ │ │ ├── 24_58_bindrcpp_0.2.3.zip
│ │ │ │ ├── 24_58_lazyeval_0.2.1.zip
│ │ │ │ ├── 1_1_assertthatbad_0.2.1.zip
│ │ │ │ ├── 1_1_assertthatinterchange_0.2.1.zip
│ │ │ │ └── 1_1_assertthatzipwithinzip_0.2.1.zip
│ │ │ └── windows
│ │ │ │ ├── 1_1_bindr_0.1.1.zip
│ │ │ │ ├── 1_1_lazyeval_0.2.2.zip
│ │ │ │ ├── 24_58_rlang_0.4.7.zip
│ │ │ │ ├── 1_1_assertthat_0.2.1.zip
│ │ │ │ ├── 1_1_pkgconfig_2.0.3.zip
│ │ │ │ ├── 24_58_bindrcpp_0.2.2.zip
│ │ │ │ ├── 24_58_lazyeval_0.2.1.zip
│ │ │ │ ├── 1_1_assertthatbad_0.2.1.zip
│ │ │ │ ├── 1_1_assertthatinterchange_0.2.1.zip
│ │ │ │ └── 1_1_assertthatzipwithinzip_0.2.1.zip
│ │ ├── src
│ │ │ ├── CMakeSettings.json
│ │ │ └── main.cpp
│ │ ├── build
│ │ │ ├── linux
│ │ │ │ ├── run-RExtension-test.sh
│ │ │ │ └── build-RExtension-test.sh
│ │ │ └── windows
│ │ │ │ ├── run-RExtension-test.cmd
│ │ │ │ └── build-RExtension-test.cmd
│ │ └── include
│ │ │ ├── Common.h
│ │ │ └── Utilities.h
│ ├── build
│ │ ├── linux
│ │ │ ├── create-RExtension-zip.sh
│ │ │ └── restore-packages.sh
│ │ └── windows
│ │ │ ├── create-RExtension-zip.cmd
│ │ │ └── restore-packages.cmd
│ ├── include
│ │ ├── Common.h
│ │ ├── Logger.h
│ │ ├── RColumn.h
│ │ ├── Utilities.h
│ │ ├── RPathSettings.h
│ │ └── REnvironment.h
│ ├── src
│ │ ├── RColumn.cpp
│ │ ├── RPathSettings.cpp
│ │ ├── linux
│ │ │ ├── RPathSettings_linux.cpp
│ │ │ └── Utilities_linux.cpp
│ │ └── windows
│ │ │ └── RPathSettings_win.cpp
│ └── common
│ │ └── include
│ │ └── Unicode.h
└── java
│ ├── build
│ ├── linux
│ │ ├── restore-packages.sh
│ │ └── create-java-extension-zip.sh
│ └── windows
│ │ ├── restore-packages.cmd
│ │ └── create-java-extension-zip.cmd
│ ├── include
│ ├── JavaSqlTypeHelper.h
│ ├── Common.h
│ ├── JavaLibraryUtils.h
│ ├── Logger.h
│ ├── JavaPathSettings.h
│ ├── JniHelper.h
│ └── JavaExtensionUtils.h
│ ├── LICENSE
│ ├── src
│ ├── windows
│ │ ├── Logger_win.cpp
│ │ └── JavaLibraryUtils_win.cpp
│ ├── JavaPathSettings.cpp
│ ├── linux
│ │ ├── Logger_linux.cpp
│ │ └── JavaLibraryUtils_linux.cpp
│ ├── JavaLibraryUtils.cpp
│ ├── Logger.cpp
│ └── JniHelper.cpp
│ ├── sdk
│ └── src
│ │ └── java
│ │ └── main
│ │ └── java
│ │ └── com
│ │ └── microsoft
│ │ └── sqlserver
│ │ └── javalangextension
│ │ └── AbstractSqlServerExtensionExecutor.java
│ └── samples
│ └── regex
│ └── readme.md
├── packages.config
├── NuGet.Config
├── restore-packages.sh
├── test
├── run-unittests.cmd
└── googletest
│ ├── src
│ ├── linux
│ │ └── CMakeLists.txt.in
│ ├── windows
│ │ └── CMakeLists.txt.in
│ └── CMakeLists.txt
│ └── build
│ ├── linux
│ └── build-googletest.sh
│ └── windows
│ └── build-googletest.cmd
├── extension-host
└── include
│ └── sqlexternallibrary.h
├── LICENSE
├── README.md
└── SECURITY.md
/restore-packages.cmd:
--------------------------------------------------------------------------------
1 | SET EnlRoot=%~dp0
2 | nuget restore %EnlRoot%packages.config -PackagesDirectory %EnlRoot%packages
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/lib/hostfxr.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/dotnet-core-CSharp/lib/hostfxr.dll
--------------------------------------------------------------------------------
/language-extensions/python/test/test_packages/astor.whl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/python/test/test_packages/astor.whl
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/linux/1_1_bindr_0.1.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/linux/1_1_bindr_0.1.1.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/linux/1_1_plogr_0.2.0.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/linux/1_1_plogr_0.2.0.zip
--------------------------------------------------------------------------------
/language-extensions/python/test/test_packages/astor-0.7.1-WHL.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/python/test/test_packages/astor-0.7.1-WHL.zip
--------------------------------------------------------------------------------
/language-extensions/python/test/test_packages/bad-package-ZIP.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/python/test/test_packages/bad-package-ZIP.zip
--------------------------------------------------------------------------------
/language-extensions/python/test/test_packages/statsd-3.3.0-WHL.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/python/test/test_packages/statsd-3.3.0-WHL.zip
--------------------------------------------------------------------------------
/language-extensions/python/test/test_packages/testpackageA-ZIP.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/python/test/test_packages/testpackageA-ZIP.zip
--------------------------------------------------------------------------------
/language-extensions/python/test/test_packages/testpackageB-ZIP.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/python/test/test_packages/testpackageB-ZIP.zip
--------------------------------------------------------------------------------
/language-extensions/python/test/test_packages/testpackageC-ZIP.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/python/test/test_packages/testpackageC-ZIP.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/linux/24_58_rlang_1.1.6.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/linux/24_58_rlang_1.1.6.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/windows/1_1_bindr_0.1.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/windows/1_1_bindr_0.1.1.zip
--------------------------------------------------------------------------------
/language-extensions/python/test/test_packages/absl-py-1.0.0-TAR.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/python/test/test_packages/absl-py-1.0.0-TAR.zip
--------------------------------------------------------------------------------
/language-extensions/python/test/test_packages/testpackagebad-ZIP.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/python/test/test_packages/testpackagebad-ZIP.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/linux/1_1_assertthat_0.2.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/linux/1_1_assertthat_0.2.1.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/linux/1_1_lazyeval_0.2.2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/linux/1_1_lazyeval_0.2.2.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/linux/1_1_pkgconfig_2.0.3.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/linux/1_1_pkgconfig_2.0.3.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/linux/24_58_bindrcpp_0.2.3.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/linux/24_58_bindrcpp_0.2.3.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/linux/24_58_lazyeval_0.2.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/linux/24_58_lazyeval_0.2.1.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/windows/1_1_lazyeval_0.2.2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/windows/1_1_lazyeval_0.2.2.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/windows/24_58_rlang_0.4.7.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/windows/24_58_rlang_0.4.7.zip
--------------------------------------------------------------------------------
/language-extensions/python/test/test_packages/Markdown-2.6.11-ZIP.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/python/test/test_packages/Markdown-2.6.11-ZIP.zip
--------------------------------------------------------------------------------
/language-extensions/python/test/test_packages/telemetry-0.3.2-TAR.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/python/test/test_packages/telemetry-0.3.2-TAR.zip
--------------------------------------------------------------------------------
/language-extensions/python/test/test_packages/termcolor-1.1.0-TAR.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/python/test/test_packages/termcolor-1.1.0-TAR.zip
--------------------------------------------------------------------------------
/language-extensions/python/test/test_packages/testpackageA-v2-ZIP.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/python/test/test_packages/testpackageA-v2-ZIP.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/windows/1_1_assertthat_0.2.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/windows/1_1_assertthat_0.2.1.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/windows/1_1_pkgconfig_2.0.3.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/windows/1_1_pkgconfig_2.0.3.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/windows/24_58_bindrcpp_0.2.2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/windows/24_58_bindrcpp_0.2.2.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/windows/24_58_lazyeval_0.2.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/windows/24_58_lazyeval_0.2.1.zip
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/sample/regex/RegexSampleResult.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/dotnet-core-CSharp/sample/regex/RegexSampleResult.PNG
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/linux/1_1_assertthatbad_0.2.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/linux/1_1_assertthatbad_0.2.1.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/windows/1_1_assertthatbad_0.2.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/windows/1_1_assertthatbad_0.2.1.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/linux/1_1_assertthatinterchange_0.2.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/linux/1_1_assertthatinterchange_0.2.1.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/linux/1_1_assertthatzipwithinzip_0.2.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/linux/1_1_assertthatzipwithinzip_0.2.1.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/windows/1_1_assertthatinterchange_0.2.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/windows/1_1_assertthatinterchange_0.2.1.zip
--------------------------------------------------------------------------------
/language-extensions/R/test/test-packages/windows/1_1_assertthatzipwithinzip_0.2.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/sql-server-language-extensions/HEAD/language-extensions/R/test/test-packages/windows/1_1_assertthatzipwithinzip_0.2.1.zip
--------------------------------------------------------------------------------
/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/sample/SubModuleCall/SubModuleProject/SubModule/SubModule.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/language-extensions/java/build/linux/restore-packages.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
4 |
5 | export DEBIAN_FRONTEND=noninteractive
6 | apt-get update
7 |
8 | apt-get --no-install-recommends -y install curl zip unzip apt-transport-https
9 |
10 | apt-get install -y openjdk-17-jdk libc++1 libc6 libc++-dev libc++abi-dev libc++abi1
11 |
12 | exit $?
13 |
--------------------------------------------------------------------------------
/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/restore-packages.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Install unixodbc-dev for development headers
4 | #
5 | apt-get -q -y install unixodbc-dev
6 |
7 | apt-get update -y
8 | apt-get install build-essential software-properties-common -y
9 | add-apt-repository ppa:ubuntu-toolchain-r/test -y
10 | apt-get update -y
11 | apt-get install gcc-13 g++-13 -y
12 | apt-get install cmake -y
13 | update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 70 --slave /usr/bin/g++ g++ /usr/bin/g++-13
14 |
15 | exit $?
16 |
17 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/build/windows/restore-packages.cmd:
--------------------------------------------------------------------------------
1 | @ECHO off
2 | SETLOCAL
3 |
4 | SET ENL_ROOT=%~dp0..\..\..\..
5 |
6 | REM Call the root level restore-packages
7 | REM
8 | SET PACKAGES_ROOT=%ENL_ROOT%\packages
9 | CALL %ENL_ROOT%\restore-packages.cmd
10 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to restore common nuget packages." || EXIT /b %ERRORLEVEL%
11 |
12 | EXIT /b %ERRORLEVEL%
13 |
14 | :CHECKERROR
15 | IF %1 NEQ 0 (
16 | ECHO %2
17 | EXIT /b %1
18 | )
19 |
20 | EXIT /b 0
21 |
--------------------------------------------------------------------------------
/language-extensions/java/build/windows/restore-packages.cmd:
--------------------------------------------------------------------------------
1 | SET ENL_ROOT=%~dp0..\..\..\..
2 | CALL %ENL_ROOT%\restore-packages.cmd
3 |
4 | SET PACKAGES_ROOT=%ENL_ROOT%\packages
5 | SET JAVA_VERSION=17.0.5
6 |
7 | REM Download and install JAVA
8 | REM
9 | SET JAVA_DOWNLOAD_URL="https://aka.ms/download-jdk/microsoft-jdk-%JAVA_VERSION%-windows-x64.zip"
10 | SET JAVA_INSTALLATION_PATH=%ProgramFiles%\JAVA
11 |
12 | curl %JAVA_DOWNLOAD_URL% -L -o "java-%JAVA_VERSION%.zip"
13 | powershell -NoProfile -ExecutionPolicy Unrestricted -Command "Expand-Archive -Force -Path 'java-%JAVA_VERSION%.zip' -DestinationPath '%PACKAGES_ROOT%'"
14 | DEL "java-%JAVA_VERSION%.zip"
15 |
--------------------------------------------------------------------------------
/language-extensions/java/include/JavaSqlTypeHelper.h:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: JavaSqlTypeHelper.h
6 | //
7 | // Purpose:
8 | // Handles converting ODBC C type to JDBC type
9 | //
10 | //*********************************************************************
11 | #pragma once
12 |
13 | #include "Common.h"
14 |
15 | class JavaSqlTypeHelper
16 | {
17 | public:
18 | static bool GetJavaSqlType(SQLSMALLINT sqlType, jint &jdbcType);
19 |
20 | static bool GetOdbcType(jint jdbcType, SQLSMALLINT &odbcType);
21 | };
22 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/src/managed/Microsoft.SqlServer.CSharpExtension.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net6.0
4 | true
5 | true
6 |
7 |
8 | $(BinRoot)/$(Configuration)/
9 | false
10 | LatestMajor
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/language-extensions/java/include/Common.h:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: Common.h
6 | //
7 | // Purpose:
8 | // Common header containing only the most common includes shared
9 | // across majority of the files
10 | //
11 | //*********************************************************************
12 | #pragma once
13 |
14 | #ifdef _WIN64
15 | #include
16 | #endif
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 |
--------------------------------------------------------------------------------
/language-extensions/java/include/JavaLibraryUtils.h:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: JavaLibraryUtils.h
6 | //
7 | // Purpose:
8 | // Library utility classes used by the Java extension.
9 | //
10 | //*********************************************************************
11 | #pragma once
12 |
13 | #include "Common.h"
14 |
15 | //---------------------------------------------------------------------
16 | // Description:
17 | // Library utility functions for the Java extension.
18 | //
19 | class JavaLibraryUtils
20 | {
21 | public:
22 | static std::string GetLibrariesClassPath();
23 |
24 | private:
25 | static void FindAppendFileNames(const std::string &basePath, std::string &output);
26 | };
27 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/test/include/Common.h:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: Common.h
6 | //
7 | // Purpose:
8 | // Common headers for .NET Core CSharpExtenion-test.
9 | //
10 | //*********************************************************************
11 | #pragma once
12 |
13 | #ifdef _WIN64
14 | #include
15 | #endif
16 |
17 | #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include "gtest/gtest.h"
26 | #include "nativecsharpextension.h"
27 | #include "CSharpExtensionApiTests.h"
--------------------------------------------------------------------------------
/test/run-unittests.cmd:
--------------------------------------------------------------------------------
1 | @ECHO off
2 | SETLOCAL
3 |
4 | :LOOP
5 |
6 | IF "%~1"=="" GOTO USAGE
7 |
8 | REM Set config to first arg
9 | REM
10 | SET MSVC_BUILD_CONFIGURATION=%1
11 |
12 | IF NOT DEFINED CDP_USER_SOURCE_FOLDER_CONTAINER_PATH (SET ENL_ROOT=%~dp0..) ELSE (SET ENL_ROOT=%CDP_USER_SOURCE_FOLDER_CONTAINER_PATH%)
13 |
14 | pushd %ENL_ROOT%\build-output\sample-test\x64\%MSVC_BUILD_CONFIGURATION%
15 | sample-test.exe --gtest_output=xml:%ENL_ROOT%\out\TestReport_sample-test.xml
16 | IF %ERRORLEVEL% NEQ 0 GOTO error
17 | popd
18 |
19 | REM Advance arg passed to this script
20 | REM
21 | SHIFT
22 |
23 | REM Continue running using more configs until args have been exhausted
24 | REM
25 | IF NOT "%~1"=="" GOTO LOOP
26 |
27 | :error
28 | EXIT /b %ERRORLEVEL%
29 |
30 | :USAGE
31 | echo.
32 | echo Usage:
33 | echo %0 { debug ^| release }
34 |
--------------------------------------------------------------------------------
/test/googletest/src/linux/CMakeLists.txt.in:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.5)
2 |
3 | project(googletest-download NONE)
4 |
5 | include(ExternalProject)
6 | ExternalProject_Add(googletest
7 | GIT_REPOSITORY https://github.com/google/googletest.git
8 | GIT_TAG release-1.12.1
9 |
10 | # GIT_CONFIG should have core.bare=false, core.symlinks=false, core.longpaths=true
11 | # for successful clone and checkout.
12 | # These are the defaults on linux. So no special configuration is needed here.
13 | # If GIT_CONFIG is at all needed, modify the cmake_minimum_required to 3.8.2.
14 | #
15 |
16 | SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
17 | BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
18 | CONFIGURE_COMMAND ""
19 | BUILD_COMMAND ""
20 | INSTALL_COMMAND ""
21 | TEST_COMMAND ""
22 | )
23 |
--------------------------------------------------------------------------------
/test/googletest/src/windows/CMakeLists.txt.in:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.8.2)
2 |
3 | project(googletest-download NONE)
4 |
5 | include(ExternalProject)
6 | ExternalProject_Add(googletest
7 | GIT_REPOSITORY https://github.com/google/googletest.git
8 | GIT_TAG release-1.12.1
9 |
10 | # Make sure core.symlinks, core.bare are set to false otherwise
11 | # git clone fails with "operation need to be run in a working tree".
12 | # Keep core.longpaths = true as a precaution to not fail on longpaths.
13 | #
14 | GIT_CONFIG core.bare=false core.symlinks=false core.longpaths=true
15 |
16 | SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
17 | BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
18 | CONFIGURE_COMMAND ""
19 | BUILD_COMMAND ""
20 | INSTALL_COMMAND ""
21 | TEST_COMMAND ""
22 | )
23 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/include/Logger.h:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: Logger.h
6 | //
7 | // Purpose:
8 | // Wrapper class around logging to standardize logging messages and errors.
9 | //
10 | //*********************************************************************
11 | #include
12 | #include
13 | #include
14 |
15 | using namespace std;
16 | #define LOG(msg) Logger::Log(msg)
17 | #define LOG_ERROR(msg) Logger::LogError(msg)
18 |
19 | class Logger
20 | {
21 | public:
22 | // Logs a message to stdout.
23 | //
24 | static void Log(const string &msg);
25 |
26 | // Logs an error to stderr
27 | //
28 | static void LogError(const string &errorMsg);
29 | };
30 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/test/src/managed/Microsoft.SqlServer.CSharpExtensionTest.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net6.0
4 | true
5 |
6 |
7 | $(BinRoot)/$(Configuration)/
8 | false
9 |
10 |
11 |
12 |
13 |
14 |
15 | ..\..\..\..\..\build-output\dotnet-core-CSharp-extension\windows\release\Microsoft.SqlServer.CSharpExtension.dll
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/sample/regex/pkg/RegexSample.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net6.0
4 | true
5 | true
6 |
7 |
8 | $(BinRoot)/$(Configuration)/
9 | false
10 |
11 |
12 |
13 |
14 |
15 |
16 | ..\..\..\..\..\build-output\dotnet-core-CSharp-extension\windows\release\Microsoft.SqlServer.CSharpExtension.dll
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/language-extensions/python/include/Common.h:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // Copyright (C) Microsoft Corporation.
3 | // Distributed under the Boost Software License, Version 1.0.
4 | // (See accompanying file LICENSE_1_0.txt or copy at
5 | // https://www.boost.org/LICENSE_1_0.txt)
6 | //
7 | // @File: Common.h
8 | //
9 | // Purpose:
10 | // Common headers for extension
11 | //
12 | //*************************************************************************************************
13 |
14 | #pragma once
15 |
16 | #ifdef _WIN64
17 | #include
18 | #endif
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 | #include
30 | #include
31 |
--------------------------------------------------------------------------------
/language-extensions/python/test/include/Common.h:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // Copyright (C) Microsoft Corporation.
3 | // Distributed under the Boost Software License, Version 1.0.
4 | // (See accompanying file LICENSE_1_0.txt or copy at
5 | // https://www.boost.org/LICENSE_1_0.txt)
6 | //
7 | // @File: Common.h
8 | //
9 | // Purpose:
10 | // Common headers for the python test project
11 | //
12 | //*************************************************************************************************
13 | #pragma once
14 |
15 | #ifdef _WIN64
16 | #include
17 | #endif
18 |
19 | #include
20 | #include
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | #include "gtest/gtest.h"
29 | #include "sqlexternallibrary.h"
30 |
--------------------------------------------------------------------------------
/language-extensions/python/test/src/main.cpp:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // Copyright (C) Microsoft Corporation.
3 | // Distributed under the Boost Software License, Version 1.0.
4 | // (See accompanying file LICENSE_1_0.txt or copy at
5 | // https://www.boost.org/LICENSE_1_0.txt)
6 | //
7 | // @File: main.cpp
8 | //
9 | // Purpose:
10 | // Initialize gtest and run all Python extension tests
11 | //
12 | //*************************************************************************************************
13 | #include
14 |
15 | int main(int argc, const char **argv)
16 | {
17 | // banner
18 | //
19 | std::cout << "Running PythonExtension C++ unit tests.\n";
20 |
21 | // First, initiate Google Test framework - this will remove
22 | // framework-specific parameters from argc and argv
23 | //
24 | ::testing::InitGoogleTest(&argc, const_cast(argv));
25 | int rc = RUN_ALL_TESTS();
26 |
27 | return rc;
28 | }
29 |
--------------------------------------------------------------------------------
/language-extensions/R/build/linux/create-RExtension-zip.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | function check_exit_code {
4 | EXIT_CODE=$?
5 | if [ ${EXIT_CODE} -eq 0 ]; then
6 | echo "Success: Created zip for $1 config"
7 | else
8 | echo "Error: Failed to create zip for $1 config"
9 | exit ${EXIT_CODE}
10 | fi
11 | }
12 |
13 | function build {
14 | BUILD_CONFIGURATION=$1
15 |
16 | SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
17 | ENL_ROOT=${SCRIPTDIR}/../../../..
18 |
19 | BUILD_OUTPUT=${ENL_ROOT}/build-output/RExtension/linux/${BUILD_CONFIGURATION}
20 |
21 | mkdir -p ${BUILD_OUTPUT}/packages
22 | cd ${BUILD_OUTPUT}
23 | zip packages/R-lang-extension-linux libRExtension.so.1.2
24 | check_exit_code ${BUILD_CONFIGURATION}
25 | }
26 |
27 | # Build in release mode if nothing is specified
28 | #
29 | if [ "$1" == "" ]; then
30 | set -- release
31 | fi
32 |
33 | while [ "$1" != "" ]; do
34 | # Advance arg passed to this script
35 | #
36 | build $1
37 | shift
38 | done;
39 |
40 | exit $?
41 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/test/src/native/main.cpp:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: main.cpp
6 | //
7 | // Purpose:
8 | // Main driver to invoke tests testing the dotnet-core-CSharp-extension's
9 | // implementation of the external language APIs.
10 | //
11 | //*********************************************************************
12 | #include "gtest/gtest.h"
13 | #include
14 |
15 | int g_argc = 0;
16 | const char **g_argv = nullptr;
17 |
18 | int main(int argc, const char **argv)
19 | {
20 | std::cout << "Running dotnetcore-CSharp-extension C++ unit tests.\n";
21 |
22 | // First, initiate Google Test framework - this will remove
23 | // framework-specific parameters from argc and argv
24 | //
25 | ::testing::InitGoogleTest(&argc, const_cast(argv));
26 | g_argc = argc;
27 | g_argv = argv;
28 |
29 | int rc = RUN_ALL_TESTS();
30 |
31 | return rc;
32 | }
33 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/sample/LoopBackConnection/README.md:
--------------------------------------------------------------------------------
1 | # Loopback Connection
2 | This example demonstrates how to establish a loopback connection to SQL server. A loopback connection will allow your C# language extension to run any custom query against SQL Server.
3 | ## Prerequisites
4 | * [LoopBackConnectionADONET.cs](LoopBackConnectionADONET.cs). This contains the ADO.NET driver implementation sample for Loopback connection.
5 | * [LoopBackCOnnectionOLEDB.cs](LoopBackConnectionOLEDB.cs). This contains the OLEDB driver implementation sample for Loopback Connection.
6 |
7 | ## Implementation Steps
8 |
9 | 1) Download/clone the this folder.
10 | 2) Depending on what driver you would like to use, edit that particual component.
11 | 3) Follow the standard method to outlined in documentation to moved the language Extension DLL code into respective folders.
12 | 4) Execute the code through a stored procedure call as outlined in the regex sample.
13 | 5) Once your run it you should be able to see the console output in SSMS.
--------------------------------------------------------------------------------
/language-extensions/java/build/linux/create-java-extension-zip.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | function check_exit_code {
4 | EXIT_CODE=$?
5 | if [ ${EXIT_CODE} -eq 0 ]; then
6 | echo "Success: Created zip for $1 config"
7 | else
8 | echo "Error: Failed to create zip for $1 config"
9 | exit ${EXIT_CODE}
10 | fi
11 | }
12 |
13 |
14 | function build {
15 | BUILD_CONFIGURATION=$1
16 |
17 | SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
18 | ENL_ROOT=${SCRIPTDIR}/../../../..
19 |
20 | BUILD_OUTPUT=${ENL_ROOT}/build-output/java-extension/linux/${BUILD_CONFIGURATION}
21 |
22 | mkdir -p ${BUILD_OUTPUT}/packages
23 | cd ${BUILD_OUTPUT}
24 | zip packages/java-lang-extension-linux libJavaExtension.so.1.0
25 | check_exit_code ${BUILD_CONFIGURATION}
26 | }
27 |
28 | # Build in release mode if nothing is specified
29 | #
30 | if [ "$1" == "" ]; then
31 | set -- release
32 | fi
33 |
34 | while [ "$1" != "" ]; do
35 | # Advance arg passed to this script
36 | #
37 | build $1
38 | shift
39 | done;
40 |
41 | exit $?
42 |
--------------------------------------------------------------------------------
/language-extensions/python/build/linux/create-python-extension-zip.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | function check_exit_code {
4 | EXIT_CODE=$?
5 | if [ ${EXIT_CODE} -eq 0 ]; then
6 | echo "Success: Created zip for $1 config"
7 | else
8 | echo "Error: Failed to create zip for $1 config"
9 | exit ${EXIT_CODE}
10 | fi
11 | }
12 |
13 |
14 | function build {
15 | BUILD_CONFIGURATION=$1
16 |
17 | SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
18 | ENL_ROOT=${SCRIPTDIR}/../../../..
19 |
20 | BUILD_OUTPUT=${ENL_ROOT}/build-output/pythonextension/linux/${BUILD_CONFIGURATION}
21 |
22 | mkdir -p ${BUILD_OUTPUT}/packages
23 | cd ${BUILD_OUTPUT}
24 | zip packages/python-lang-extension-linux libPythonExtension.so.1.2
25 | check_exit_code ${BUILD_CONFIGURATION}
26 | }
27 |
28 | # Build in release mode if nothing is specified
29 | #
30 | if [ "$1" == "" ]; then
31 | set -- release
32 | fi
33 |
34 | while [ "$1" != "" ]; do
35 | # Advance arg passed to this script
36 | #
37 | build $1
38 | shift
39 | done;
40 |
41 | exit $?
42 |
--------------------------------------------------------------------------------
/test/googletest/build/linux/build-googletest.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | function check_exit_code {
4 | EXIT_CODE=$?
5 | if [ ${EXIT_CODE} -eq 0 ]; then
6 | echo $1
7 | else
8 | echo $2
9 | exit ${EXIT_CODE}
10 | fi
11 | }
12 |
13 | # Enlistment root and location of googletest
14 | #
15 | SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
16 | ENL_ROOT=${SCRIPTDIR}/../../../..
17 | PACKAGES_ROOT=${ENL_ROOT}/packages
18 | GTEST_HOME=${ENL_ROOT}/test/googletest
19 |
20 | # Set environment variables required in cmake
21 | #
22 | BUILD_OUTPUT=${ENL_ROOT}/build-output/googletest/linux
23 |
24 | # Generate the build output directory
25 | #
26 | rm -rf ${BUILD_OUTPUT}
27 | mkdir -p ${BUILD_OUTPUT}
28 | pushd ${BUILD_OUTPUT}
29 |
30 | # Compile
31 | #
32 | cmake -DCMAKE_INSTALL_PREFIX:PATH=${BUILD_OUTPUT} \
33 | -DPLATFORM=linux \
34 | ${GTEST_HOME}/src
35 | cmake --build ${BUILD_OUTPUT} --target install
36 |
37 | # Check the exit code of the compiler and exit appropriately so that build will fail.
38 | #
39 | check_exit_code "Success: Built googletest" "Error: Failed to build Rextension-test"
40 |
41 | popd
42 |
43 | exit $?
44 |
--------------------------------------------------------------------------------
/language-extensions/python/test/include/PythonTestUtilities.h:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // Copyright (C) Microsoft Corporation.
3 | // Distributed under the Boost Software License, Version 1.0.
4 | // (See accompanying file LICENSE_1_0.txt or copy at
5 | // https://www.boost.org/LICENSE_1_0.txt)
6 | //
7 | // @File: PythonTestUtilities.h
8 | //
9 | // Purpose:
10 | // Utility functions for the tests
11 | //
12 | //*************************************************************************************************
13 |
14 | #pragma once
15 | #include "Common.h"
16 |
17 | class PythonTestUtilities
18 | {
19 | public:
20 |
21 | // Parses the value of the active python exception
22 | // Type, value, and traceback are in separate pointers
23 | //
24 | static std::string ParsePythonException();
25 |
26 | // Extract the string from a boost::python object
27 | //
28 | static std::string ExtractString(PyObject * pObj);
29 | static std::string ExtractString(boost::python::object handle);
30 | static void Tokenize(char *input, const char *delimiter, std::vector *tokens);
31 | };
32 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/src/native/Logger.cpp:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: Logger.cpp
6 | //
7 | // Purpose:
8 | // Wrapper class around logging to standardize logging messages and errors.
9 | //
10 | //*********************************************************************
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include "Logger.h"
16 |
17 | using namespace std;
18 |
19 | //--------------------------------------------------------------------------------------------------
20 | // Name: Logger::Log
21 | //
22 | // Description:
23 | // Logs a message to stdout.
24 | //
25 | void Logger::Log(const string &msg)
26 | {
27 | #ifdef DEBUG
28 | cout << msg <
14 | #include
15 |
16 | #define TIMESTAMP_LENGTH 35
17 |
18 | using namespace std;
19 |
20 | char Logger::timestampBuffer[TIMESTAMP_LENGTH] = {0};
21 |
22 | //---------------------------------------------------------------------
23 | // Name: GetCurrentTimestamp
24 | //
25 | // Description:
26 | // Gets the current system time and format it to the SQL log format
27 | // (Year-Month-Day Hour:Minute:Second.Millisecond).
28 | //
29 | const char* Logger::GetCurrentTimestamp()
30 | {
31 | SYSTEMTIME sysTime;
32 |
33 | GetLocalTime(&sysTime);
34 |
35 | sprintf_s(timestampBuffer, TIMESTAMP_LENGTH,
36 | "%04d-%02d-%02d %02d:%02d:%02d.%02d\t",
37 | sysTime.wYear,
38 | sysTime.wMonth,
39 | sysTime.wDay,
40 | sysTime.wHour,
41 | sysTime.wMinute,
42 | sysTime.wSecond,
43 | sysTime.wMilliseconds / 10);
44 |
45 | return timestampBuffer;
46 | }
47 |
--------------------------------------------------------------------------------
/language-extensions/R/build/windows/create-RExtension-zip.cmd:
--------------------------------------------------------------------------------
1 | @ECHO off
2 | SETLOCAL
3 |
4 | SET ENL_ROOT=%~dp0..\..\..\..
5 |
6 | :LOOP
7 |
8 | REM Set cmake config to first arg
9 | REM
10 | SET BUILD_CONFIGURATION=%1
11 |
12 | REM Setting BUILD_CONFIGURATION to anything but "debug" will set BUILD_CONFIGURATION to "release".
13 | REM The string comparison for BUILD_CONFIGURATION is case-insensitive.
14 | REM
15 | IF NOT DEFINED BUILD_CONFIGURATION (SET BUILD_CONFIGURATION=release)
16 | IF /I NOT %BUILD_CONFIGURATION%==debug (SET BUILD_CONFIGURATION=release)
17 |
18 | SET BUILD_OUTPUT=%ENL_ROOT%\build-output\RExtension\windows\%BUILD_CONFIGURATION%
19 |
20 | mkdir %BUILD_OUTPUT%\packages
21 |
22 | powershell -NoProfile -ExecutionPolicy Unrestricted -Command "Compress-Archive -Path %BUILD_OUTPUT%\libRExtension.dll -DestinationPath %BUILD_OUTPUT%\packages\R-lang-extension.zip -Force"
23 |
24 | CALL :CHECK_BUILD_ERROR %ERRORLEVEL% %BUILD_CONFIGURATION%
25 |
26 | REM Advance arg passed to create-RExtension-zip.cmd
27 | REM
28 | SHIFT
29 |
30 | REM Continue building using more configs until argv has been exhausted
31 | REM
32 | IF NOT "%~1"=="" GOTO LOOP
33 |
34 | EXIT /b %ERRORLEVEL%
35 |
36 | :CHECK_BUILD_ERROR
37 | IF %1 == 0 (
38 | ECHO Success: Created zip for %2 config
39 | ) ELSE (
40 | ECHO Error: Failed to create zip for %2 config
41 | EXIT /b %1
42 | )
43 |
--------------------------------------------------------------------------------
/language-extensions/java/sdk/src/java/main/java/com/microsoft/sqlserver/javalangextension/AbstractSqlServerExtensionExecutor.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.sqlserver.javalangextension;
2 |
3 | import com.microsoft.sqlserver.javalangextension.AbstractSqlServerExtensionDataset;
4 | import java.lang.UnsupportedOperationException;
5 | import java.util.LinkedHashMap;
6 |
7 | /**
8 | * Abstract class containing interface used by the Java extension
9 | */
10 | public abstract class AbstractSqlServerExtensionExecutor {
11 | /* Supported versions of the Java extension */
12 | public final int SQLSERVER_JAVA_LANG_EXTENSION_V1 = 1;
13 |
14 | /* Members used by the extension to determine application specifics */
15 | protected int executorExtensionVersion;
16 | protected String executorInputDatasetClassName;
17 | protected String executorOutputDatasetClassName;
18 |
19 | public AbstractSqlServerExtensionExecutor() { }
20 |
21 | public void init(String sessionId, int taskId, int numTasks) {
22 | /* Default implementation of init() is no-op */
23 | }
24 |
25 | public AbstractSqlServerExtensionDataset execute(AbstractSqlServerExtensionDataset input, LinkedHashMap params) {
26 | throw new UnsupportedOperationException("AbstractSqlServerExtensionExecutor execute() is not implemented");
27 | }
28 |
29 | public void cleanup() {
30 | /* Default implementation of cleanup() is no-op */
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/language-extensions/python/include/Logger.h:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // Copyright (C) Microsoft Corporation.
3 | // Distributed under the Boost Software License, Version 1.0.
4 | // (See accompanying file LICENSE_1_0.txt or copy at
5 | // https://www.boost.org/LICENSE_1_0.txt)
6 | //
7 | // @File: Logger.h
8 | //
9 | // Purpose:
10 | // Logging functions for extension
11 | //
12 | //*************************************************************************************************
13 |
14 | #pragma once
15 | #include "Common.h"
16 |
17 | #define LOG(msg) Logger::Log(msg)
18 | #define LOG_ERROR(msg) Logger::LogError(msg)
19 | #define LOG_EXCEPTION(e) Logger::LogException(e)
20 |
21 | class Logger
22 | {
23 | public:
24 | // Log an error to stderr
25 | //
26 | static void LogError(const std::string &errorMsg);
27 |
28 | // Log a extension exception to stderr
29 | //
30 | static void LogException(const std::exception &e);
31 |
32 | // Log a message to stdout
33 | //
34 | static void Log(const std::string &msg);
35 |
36 | private:
37 | // Get a string of the current timestamp in the same format
38 | // of SQL format
39 | //
40 | static const std::string GetCurrentTimestamp();
41 |
42 | // Buffer to hold the timestamp string.
43 | //
44 | static char sm_timestampBuffer[];
45 | };
46 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/test/build/windows/run-dotnet-core-CSharp-extension-test.cmd:
--------------------------------------------------------------------------------
1 | @ECHO off
2 | SETLOCAL
3 |
4 | REM Set environment variables
5 | REM
6 | SET ENL_ROOT=%~dp0..\..\..\..\..
7 | SET DOTNETCORE_CSHARP_EXTENSION_TEST_WORKING_DIR=%ENL_ROOT%\build-output\dotnet-core-csharp-extension-test\windows
8 | SET PACKAGES_ROOT=%ENL_ROOT%\packages
9 | SET GTEST_HOME=%PACKAGES_ROOT%\Microsoft.googletest.v140.windesktop.msvcstl.dyn.rt-dyn.1.8.1.3
10 | SET GTEST_LIB_PATH=%GTEST_HOME%\lib\native\v140\windesktop\msvcstl\dyn\rt-dyn\x64
11 |
12 | :LOOP
13 |
14 | REM Set cmake config to first arg
15 | REM
16 | SET CMAKE_CONFIGURATION=%1
17 |
18 | REM CMAKE_CONFIGURATION is debug by default if not defined.
19 | REM
20 | IF NOT DEFINED CMAKE_CONFIGURATION (SET CMAKE_CONFIGURATION=release)
21 |
22 | PUSHD %DOTNETCORE_CSHARP_EXTENSION_TEST_WORKING_DIR%\%CMAKE_CONFIGURATION%
23 | COPY %GTEST_LIB_PATH%\%CMAKE_CONFIGURATION%\gtest*.dll .
24 | dotnet-core-CSharp-extension-test.exe --gtest_output=xml:%ENL_ROOT%\out\TestReport_dotnet-core-csharp-extension-test.xml
25 | IF %ERRORLEVEL% NEQ 0 GOTO error
26 | POPD
27 |
28 | REM Advance arg passed to run-dotnet-core-csharp-extension-test.cmd
29 | REM
30 | SHIFT
31 |
32 | REM Continue running using more configs until argv has been exhausted
33 | REM
34 | IF NOT "%~1"=="" GOTO LOOP
35 |
36 | :error
37 | EXIT /b %ERRORLEVEL%
38 |
39 | :USAGE
40 | echo.
41 | echo Usage:
42 | echo %0 { debug ^| release }
43 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/test/src/native/CSharpInitSessionTests.cpp:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: CSharpInitSessionTests.cpp
6 | //
7 | // Purpose:
8 | // Test the .NET Core CSharp extension initialization and
9 | // session initialization using the Extension API
10 | //
11 | //*********************************************************************
12 | #include "CSharpExtensionApiTests.h"
13 |
14 | using namespace std;
15 |
16 | namespace ExtensionApiTest
17 | {
18 | //----------------------------------------------------------------------------------------------
19 | // Name: InitValidSessionTest
20 | //
21 | // Description:
22 | // Test InitSession() API with valid values.
23 | //
24 | TEST_F(CSharpExtensionApiTests, InitValidSessionTest)
25 | {
26 | SQLRETURN result = (*sm_initSessionFuncPtr)(
27 | *m_sessionId,
28 | m_taskId,
29 | m_numTasks,
30 | m_script,
31 | m_scriptString.length(),
32 | m_inputSchemaColumnsNumber,
33 | m_parametersNumber,
34 | m_inputDataName,
35 | m_inputDataNameString.length(),
36 | m_outputDataName,
37 | m_outputDataNameString.length());
38 |
39 | EXPECT_EQ(result, SQL_SUCCESS);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/language-extensions/java/include/Logger.h:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: Logger.h
6 | //
7 | // Purpose:
8 | // Wrapper class around logging to standardize logging messages
9 | // and errors.
10 | //
11 | //*********************************************************************
12 | #pragma once
13 |
14 | #include "Common.h"
15 |
16 | #ifdef DEBUG
17 | #define LOG(msg) Logger::Log(msg)
18 | #else
19 | #define LOG(msg)
20 | #endif
21 | #define LOG_ERROR(msg) Logger::LogError(msg)
22 | #define LOG_EXCEPTION(e) Logger::LogException(e)
23 | #define LOG_JAVA_EXCEPTION(msg) Logger::LogJavaException(msg)
24 |
25 | class Logger
26 | {
27 | public:
28 | // Log an error to stderr
29 | //
30 | static void LogError(const std::string &errorMsg);
31 |
32 | // Log a extension exception to stderr
33 | //
34 | static void LogException(const std::exception &e);
35 |
36 | // Log a java exception to stderr
37 | //
38 | static void LogJavaException(const std::string &errorMsg);
39 |
40 | // Log a message to stdout
41 | //
42 | static void Log(const std::string &errorMsg);
43 |
44 | private:
45 | // Get a string of the current timestamp in the same format
46 | // of SQL format
47 | //
48 | static const char* GetCurrentTimestamp();
49 |
50 | // Buffer to hold the timestamp string.
51 | //
52 | static char timestampBuffer[];
53 | };
54 |
--------------------------------------------------------------------------------
/extension-host/include/sqlexternallibrary.h:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | //
4 | // Library management protocol between Exthost and a 3rd party extension
5 | //
6 | // @File: sqlexternallibrary.h
7 | //
8 | //*********************************************************************
9 |
10 | #ifndef __SQLEXTERNALLIBRARY
11 | #define __SQLEXTERNALLIBRARY
12 |
13 | #include "sqlexternallanguage.h"
14 |
15 | #ifdef __cplusplus
16 | extern "C" {
17 | #endif /* __cplusplus */
18 |
19 | // Optional API
20 | //
21 | SQLEXTENSION_INTERFACE
22 | SQLRETURN InstallExternalLibrary(
23 | SQLGUID SetupSessionId,
24 | SQLCHAR *LibraryName,
25 | SQLINTEGER LibraryNameLength,
26 | SQLCHAR *LibraryFile,
27 | SQLINTEGER LibraryFileLength,
28 | SQLCHAR *LibraryInstallDirectory,
29 | SQLINTEGER LibraryInstallDirectoryLength,
30 | SQLCHAR **LibraryError,
31 | SQLINTEGER *LibraryErrorLength);
32 |
33 | // Optional API
34 | //
35 | SQLEXTENSION_INTERFACE
36 | SQLRETURN UninstallExternalLibrary(
37 | SQLGUID SetupSessionId,
38 | SQLCHAR *LibraryName,
39 | SQLINTEGER LibraryNameLength,
40 | SQLCHAR *LibraryInstallDirectory,
41 | SQLINTEGER LibraryInstallDirectoryLength,
42 | SQLCHAR **LibraryError,
43 | SQLINTEGER *LibraryErrorLength);
44 |
45 | #ifdef __cplusplus
46 | } /* End of extern "C" { */
47 | #endif /* __cplusplus */
48 |
49 | #endif /* __SQLEXTERNALLIBRARY */
50 |
--------------------------------------------------------------------------------
/language-extensions/python/LICENSE_1_0.txt:
--------------------------------------------------------------------------------
1 | Boost Software License - Version 1.0 - August 17th, 2003
2 |
3 | Permission is hereby granted, free of charge, to any person or organization
4 | obtaining a copy of the software and accompanying documentation covered by
5 | this license (the "Software") to use, reproduce, display, distribute,
6 | execute, and transmit the Software, and to prepare derivative works of the
7 | Software, and to permit third-parties to whom the Software is furnished to
8 | do so, all subject to the following:
9 |
10 | The copyright notices in the Software and this entire statement, including
11 | the above license grant, this restriction and the following disclaimer,
12 | must be included in all copies of the Software, in whole or in part, and
13 | all derivative works of the Software, unless such copies or derivative
14 | works are solely in the form of machine-executable object code generated by
15 | a source language processor.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | DEALINGS IN THE SOFTWARE.
24 |
--------------------------------------------------------------------------------
/test/googletest/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Downloads and unpacks googletest at configure time. Based on the instructions
2 | # at https://github.com/google/googletest/tree/master/googletest#incorporating-into-an-existing-cmake-project
3 |
4 | cmake_minimum_required (VERSION 3.5)
5 |
6 | project(googletest)
7 |
8 | set(CMAKE_CXX_STANDARD 17)
9 |
10 | # Populate the CMakeLists.txt.in with the actual values from build
11 | #
12 | configure_file(${PLATFORM}/CMakeLists.txt.in googletest-download/CMakeLists.txt)
13 |
14 | # Generate the make files
15 | #
16 | execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . -DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}
17 | RESULT_VARIABLE result
18 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download)
19 | if(result)
20 | message(FATAL_ERROR "CMake step for googletest failed: ${result}")
21 | endif()
22 |
23 | # Build googletest
24 | #
25 | execute_process(COMMAND "${CMAKE_COMMAND}" --build .
26 | RESULT_VARIABLE result
27 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
28 | if(result)
29 | message(FATAL_ERROR "Build step for googletest failed: ${result}")
30 | endif()
31 |
32 | # Prevent overriding the parent project's compiler/linker
33 | # settings on Windows
34 | #
35 | set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
36 |
37 | # Add googletest directly to build. This defines
38 | # the gtest and gtest_main targets.
39 | #
40 | add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src
41 | ${CMAKE_CURRENT_BINARY_DIR}/googletest-build)
42 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/src/managed/utils/ExceptionUtils.cs:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: ExceptionUtils.cs
6 | //
7 | // Purpose:
8 | // Handle the exceptions from managed language extensions APIs
9 | //
10 | //*********************************************************************
11 | using System;
12 | using static Microsoft.SqlServer.CSharpExtension.Sql;
13 |
14 | namespace Microsoft.SqlServer.CSharpExtension
15 | {
16 | ///
17 | /// This class handles the exceptions from managed language extensions APIs and
18 | /// logs the error messages to the stderr.
19 | ///
20 | class ExceptionUtils
21 | {
22 | ///
23 | /// This method calls the APIs and handles exceptions.
24 | ///
25 | ///
26 | /// Managed language extensions APIs fucntion
27 | ///
28 | ///
29 | /// SQL_SUCCESS(0), SQL_ERROR(-1)
30 | ///
31 | public static short WrapError(Action func)
32 | {
33 | try
34 | {
35 | func();
36 | return SQL_SUCCESS;
37 | }
38 | catch (Exception e)
39 | {
40 | Logging.Error(e.StackTrace + "Error: " + e.Message);
41 | return SQL_ERROR;
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/sample/SubModuleCall/SubModuleProject/SubModule/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | namespace UserExecutor
7 | {
8 | // Lets assume that a DLL is created using this kind of code in another project.
9 | // The DLL is moved into the folder where access is granted.
10 | // You need to grant access to the DLL's parent folder before you execute these commands.
11 | // To grant access to the folder, run the following commands in Windows command prompt:
12 | // Note: The folder name may change in your environment. So please specify the right folder name.
13 | // Command1:
14 | // icacls "C:\Program Files\Microsoft SQL Server\MSSQL16.SQLSERVER2022\MSSQL\ExternalLibraries\6\65537\1" /grant "SQLRUsergroupSQLSERVER2022":(OI)(CI)RX /T
15 | // Change the server name according to your naming convension .
16 | // Command2:
17 | // icacls "C:\Program Files\Microsoft SQL Server\MSSQL16.SQLSERVER2022\MSSQL\ExternalLibraries\6\65537\1" /grant *S-1-15-2-1:(OI)(CI)RX /T
18 | // After executing above commands, SQL server will have access to local folder which has been specified in the commands.
19 | // All these commands are available in OneTimeSetupCommands.cmd file in this solution as well
20 | //
21 | public class SubModule
22 | {
23 | public void printConsole()
24 | {
25 | Console.WriteLine("This is hello world from adhoc DLL file");
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/include/coreclr_delegates.h:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 |
4 | #ifndef __CORECLR_DELEGATES_H__
5 | #define __CORECLR_DELEGATES_H__
6 |
7 | #include
8 |
9 | #if defined(_WIN32)
10 | #define CORECLR_DELEGATE_CALLTYPE __stdcall
11 | #ifdef _WCHAR_T_DEFINED
12 | typedef wchar_t char_t;
13 | #else
14 | typedef unsigned short char_t;
15 | #endif
16 | #else
17 | #define CORECLR_DELEGATE_CALLTYPE
18 | typedef char char_t;
19 | #endif
20 |
21 | // Signature of delegate returned by coreclr_delegate_type::load_assembly_and_get_function_pointer
22 | typedef int (CORECLR_DELEGATE_CALLTYPE *load_assembly_and_get_function_pointer_fn)(
23 | const char_t *assembly_path /* Fully qualified path to assembly */,
24 | const char_t *type_name /* Assembly qualified type name */,
25 | const char_t *method_name /* Public static method name compatible with delegateType */,
26 | const char_t *delegate_type_name /* Assembly qualified delegate type name or null */,
27 | void *reserved /* Extensibility parameter (currently unused and must be 0) */,
28 | /*out*/ void **delegate /* Pointer where to store the function pointer result */);
29 |
30 | // Signature of delegate returned by load_assembly_and_get_function_pointer_fn when delegate_type_name == null (default)
31 | typedef int (CORECLR_DELEGATE_CALLTYPE *component_entry_point_fn)(void *arg, int32_t arg_size_in_bytes);
32 |
33 | #endif // __CORECLR_DELEGATES_H__
34 |
--------------------------------------------------------------------------------
/language-extensions/java/src/JavaPathSettings.cpp:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: JavaPathSettings.cpp
6 | //
7 | // Purpose:
8 | // Global class to keep language runtime settings.
9 | //
10 | //*********************************************************************
11 | #include "JavaPathSettings.h"
12 |
13 | //----------------------------------------------------------------------------
14 | // Name: ExtensionConfig::Init
15 | //
16 | // Description:
17 | // Initialize the class
18 | //
19 | void
20 | JavaPathSettings::Init(
21 | const SQLCHAR *languageParams,
22 | const SQLCHAR *languagePath,
23 | const SQLCHAR *publicLibraryPath,
24 | const SQLCHAR *privateLibraryPath)
25 | {
26 | // nullptrs are mapped to empty strings - has the same effect when
27 | // the paths are used and avoids an additional flag.
28 | //
29 | m_languageParams =
30 | (languageParams == nullptr) ? "" : reinterpret_cast(languageParams);
31 |
32 | m_languagePath =
33 | (languagePath == nullptr) ? "" : reinterpret_cast(languagePath);
34 |
35 | m_publicLibraryPath =
36 | (publicLibraryPath == nullptr) ? "" : reinterpret_cast(publicLibraryPath);
37 |
38 | m_privateLibraryPath =
39 | (privateLibraryPath == nullptr) ? "" : reinterpret_cast(privateLibraryPath);
40 | }
41 |
42 | std::string JavaPathSettings::m_languagePath;
43 | std::string JavaPathSettings::m_languageParams;
44 | std::string JavaPathSettings::m_privateLibraryPath;
45 | std::string JavaPathSettings::m_publicLibraryPath;
46 |
--------------------------------------------------------------------------------
/language-extensions/java/include/JavaPathSettings.h:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: JavaPathSettings.h
6 | //
7 | // Purpose:
8 | // Global class to keep language runtime settings.
9 | //
10 | //*********************************************************************
11 | #pragma once
12 |
13 | #include "Common.h"
14 |
15 | //---------------------------------------------------------------------
16 | // Description:
17 | // Global class storing the language runtime paths and parameters
18 | //
19 | class JavaPathSettings
20 | {
21 | public:
22 | // Initialize this global class
23 | //
24 | static void Init(
25 | const SQLCHAR *languageParams,
26 | const SQLCHAR *languagePath,
27 | const SQLCHAR *publicLibraryPath,
28 | const SQLCHAR *privateLibraryPath);
29 |
30 | // Get the private library path sent by SQL Server
31 | //
32 | static const std::string& GetPrivateLibraryPath() { return m_privateLibraryPath; }
33 |
34 | // Get the public library path sent by SQL Server
35 | //
36 | static const std::string& GetPublicLibraryPath() { return m_publicLibraryPath; }
37 |
38 | // Get the extension root folder
39 | //
40 | static const std::string& GetRootPath() { return m_languagePath; }
41 |
42 | // Get the language parameters sent by SQL Server
43 | //
44 | static const std::string& GetParams() { return m_languageParams; }
45 |
46 | private:
47 | static std::string m_languagePath;
48 | static std::string m_languageParams;
49 | static std::string m_privateLibraryPath;
50 | static std::string m_publicLibraryPath;
51 | };
52 |
--------------------------------------------------------------------------------
/language-extensions/python/build/windows/create-python-extension-zip.cmd:
--------------------------------------------------------------------------------
1 | @ECHO off
2 | SETLOCAL
3 |
4 | SET ENL_ROOT=%~dp0..\..\..\..
5 |
6 | :LOOP
7 |
8 | REM Set cmake config to first arg
9 | REM
10 | SET BUILD_CONFIGURATION=%1
11 |
12 | REM Setting BUILD_CONFIGURATION to anything but "debug" will set BUILD_CONFIGURATION to "release".
13 | REM The string comparison for BUILD_CONFIGURATION is case-insensitive.
14 | REM
15 | IF NOT DEFINED BUILD_CONFIGURATION (SET BUILD_CONFIGURATION=release)
16 | IF /I NOT %BUILD_CONFIGURATION%==debug (SET BUILD_CONFIGURATION=release)
17 |
18 | SET BUILD_OUTPUT=%ENL_ROOT%\build-output\pythonextension\windows\%BUILD_CONFIGURATION%
19 |
20 | mkdir %BUILD_OUTPUT%\packages
21 |
22 | REM Check if BUILD_CONFIGURATION is debug, then include pythonextension.pdb in the zip
23 | IF /I "%BUILD_CONFIGURATION%"=="debug" (
24 | SET INCLUDE_FILES=%BUILD_OUTPUT%\pythonextension.dll, %BUILD_OUTPUT%\pythonextension.pdb
25 | ) ELSE (
26 | SET INCLUDE_FILES=%BUILD_OUTPUT%\pythonextension.dll
27 | )
28 |
29 | powershell -NoProfile -ExecutionPolicy Unrestricted -Command "Compress-Archive -Path %INCLUDE_FILES% -DestinationPath %BUILD_OUTPUT%\packages\python-lang-extension.zip -Force"
30 |
31 | CALL :CHECK_BUILD_ERROR %ERRORLEVEL% %BUILD_CONFIGURATION%
32 |
33 | REM Advance arg passed to create-python-extension.cmd
34 | REM
35 | SHIFT
36 |
37 | REM Continue building using more configs until argv has been exhausted
38 | REM
39 | IF NOT "%~1"=="" GOTO LOOP
40 |
41 | EXIT /b %ERRORLEVEL%
42 |
43 | :CHECK_BUILD_ERROR
44 | IF %1 == 0 (
45 | ECHO Success: Created zip for %2 config
46 | ) ELSE (
47 | ECHO Error: Failed to create zip for %2 config
48 | EXIT /b %1
49 | )
50 |
--------------------------------------------------------------------------------
/language-extensions/java/src/linux/Logger_linux.cpp:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: Logger.cpp
6 | //
7 | // Purpose:
8 | // Implementation of Linux platform dependent logging for the java
9 | // extension.
10 | //
11 | //*********************************************************************
12 | #include "Logger.h"
13 | #include
14 | #include
15 |
16 | #define TIMESTAMP_LENGTH 35
17 | #define NANOSECONDS_IN_MILLISECOND 1000000
18 |
19 | using namespace std;
20 |
21 | char Logger::timestampBuffer[TIMESTAMP_LENGTH] = {0};
22 |
23 | //---------------------------------------------------------------------
24 | // Name: GetCurrentTimestamp
25 | //
26 | // Description:
27 | // Gets the current system time and format it to the SQL log format
28 | // (Year-Month-Day Hour:Minute:Second.Millisecond).
29 | //
30 | const char* Logger::GetCurrentTimestamp()
31 | {
32 | timespec ts;
33 | char buffer[TIMESTAMP_LENGTH] = {0};
34 |
35 | clock_gettime(CLOCK_REALTIME, &ts);
36 |
37 | // Convert the time to Year-Month-Day Hour:Minute:Second
38 | //
39 | strftime(buffer, sizeof(buffer), "%F %T", gmtime(&ts.tv_sec));
40 |
41 | // Append the milliseconds and the tab to the timestamp
42 | //
43 | long ms = (ts.tv_nsec / NANOSECONDS_IN_MILLISECOND);
44 |
45 | // SQL outputs milliseconds in decimal with precision of 2, divide
46 | // by 10 to remove the last digit.
47 | //
48 | ms /= 10;
49 |
50 | // Append the milliseconds and the tab to the timestamp
51 | //
52 | sprintf(timestampBuffer, "%s.%02li\t", buffer, ms);
53 |
54 | return timestampBuffer;
55 | }
56 |
--------------------------------------------------------------------------------
/language-extensions/java/build/windows/create-java-extension-zip.cmd:
--------------------------------------------------------------------------------
1 | @ECHO off
2 | SETLOCAL
3 |
4 | SET ENL_ROOT=%~dp0..\..\..\..
5 |
6 | :LOOP
7 |
8 | REM Set cmake config to first arg
9 | REM
10 | SET BUILD_CONFIGURATION=%1
11 |
12 | REM Setting BUILD_CONFIGURATION to anything but "debug" will set BUILD_CONFIGURATION to "release".
13 | REM The string comparison for BUILD_CONFIGURATION is case-insensitive.
14 | REM
15 | IF NOT DEFINED BUILD_CONFIGURATION (SET BUILD_CONFIGURATION=release)
16 | IF /I NOT %BUILD_CONFIGURATION%==debug (SET BUILD_CONFIGURATION=release)
17 |
18 | SET BUILD_OUTPUT=%ENL_ROOT%\build-output\java-extension\windows\%BUILD_CONFIGURATION%
19 |
20 | mkdir %BUILD_OUTPUT%\packages
21 |
22 | REM Set common files to be included in the zip
23 | SET INCLUDE_FILES=%BUILD_OUTPUT%\javaextension.dll
24 |
25 | REM Check if BUILD_CONFIGURATION is debug, then include javaextension.pdb in the zip
26 | IF /I "%BUILD_CONFIGURATION%"=="debug" (
27 | SET INCLUDE_FILES=%INCLUDE_FILES%, %BUILD_OUTPUT%\javaextension.pdb
28 | )
29 |
30 | powershell -NoProfile -ExecutionPolicy Unrestricted -Command "Compress-Archive -Path %INCLUDE_FILES% -DestinationPath %BUILD_OUTPUT%\packages\java-lang-extension.zip -Force"
31 | CALL :CHECK_BUILD_ERROR %ERRORLEVEL% %BUILD_CONFIGURATION%
32 |
33 | REM Advance arg passed to create-java-extension.cmd
34 | REM
35 | SHIFT
36 |
37 | REM Continue building using more configs until argv has been exhausted
38 | REM
39 | IF NOT "%~1"=="" GOTO LOOP
40 |
41 | EXIT /b %ERRORLEVEL%
42 |
43 | :CHECK_BUILD_ERROR
44 | IF %1 == 0 (
45 | ECHO Success: Created zip for %2 config
46 | ) ELSE (
47 | ECHO Error: Failed to create zip for %2 config
48 | EXIT /b %1
49 | )
50 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/src/managed/CSharpDataSet.cs:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: CSharpDataSet.cs
6 | //
7 | // Purpose:
8 | // Class handling loading and retrieving data from a DataFrame.
9 | //
10 | //*********************************************************************
11 | using System.Collections.Generic;
12 | using Microsoft.Data.Analysis;
13 |
14 | namespace Microsoft.SqlServer.CSharpExtension
15 | {
16 | ///
17 | /// This class loads and retrieves input/output dataset.
18 | ///
19 | public abstract class CSharpDataSet
20 | {
21 | public string Name { get; set; }
22 | public ushort ColumnsNumber { get; set; }
23 |
24 | ///
25 | /// This dataframe contains input/output dataset.
26 | ///
27 | public DataFrame CSharpDataFrame { get; set; }
28 |
29 | ///
30 | /// This property defines [] operator for CSharpDataSet.
31 | ///
32 | public CSharpColumn this[ushort columnNumber]
33 | {
34 | get
35 | {
36 | return _columns[columnNumber];
37 | }
38 |
39 | private set
40 | {
41 | _columns[columnNumber] = value;
42 | }
43 | }
44 |
45 | ///
46 | /// This dictionary contains all the columns metadata as CSharpColumn objects.
47 | ///
48 | protected Dictionary _columns = new Dictionary();
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 |
3 | Microsoft SQL Server Language Extensions
4 |
5 | Copyright (c) Microsoft Corporation. All rights reserved.
6 |
7 | This repository contains language extensions for SQL Server that are separately licensed. Each language extension is contained in a separate folder accessible from the main repository and is licensed in accordance with the LICENSE.TXT file present in such folder.
8 |
9 | For all other material that is available from this repository, the following license applies.
10 |
11 | MIT License
12 | Copyright (c) Microsoft Corporation. All rights reserved.
13 |
14 | Permission is hereby granted, free of charge, to any person obtaining a copy
15 | of this software and associated documentation files (the "Software"), to deal
16 | in the Software without restriction, including without limitation the rights
17 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18 | copies of the Software, and to permit persons to whom the Software is
19 | furnished to do so, subject to the following conditions:
20 |
21 | The above copyright notice and this permission notice shall be included in all
22 | copies or substantial portions of the Software.
23 |
24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 | SOFTWARE
31 |
--------------------------------------------------------------------------------
/language-extensions/R/test/build/linux/run-RExtension-test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | function check_exit_code {
4 | EXIT_CODE=$?
5 | if [ ${EXIT_CODE} -eq 0 ]; then
6 | echo $1
7 | else
8 | echo $2
9 | exit ${EXIT_CODE}
10 | fi
11 | }
12 |
13 | function build {
14 | # Set cmake config to first arg
15 | CMAKE_CONFIGURATION=$1
16 | if [ -z "${CMAKE_CONFIGURATION}" ]; then
17 | CMAKE_CONFIGURATION=release
18 | fi
19 |
20 | pushd ${REXTENSIONTEST_WORKING_DIR}/${CMAKE_CONFIGURATION}
21 | # Move the generated libs to configuration folder
22 | cp ${REXTENSION_WORKING_DIR}/${CMAKE_CONFIGURATION}/libRExtension.so.1.2 .
23 | ./RExtension-test --gtest_output=xml:${ENL_ROOT}/out/TestReport_RExtension-test.xml
24 |
25 | # Check the exit code of the tests.
26 | check_exit_code "Success: Ran RExtension-test" "Error: RExtension-test failed"
27 |
28 | popd
29 | }
30 |
31 | # Enlistment root and location of RExtension-test
32 | SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
33 | export ENL_ROOT=${SCRIPTDIR}/../../../../..
34 | REXTENSION_WORKING_DIR=${ENL_ROOT}/build-output/RExtension/linux
35 | REXTENSIONTEST_WORKING_DIR=${ENL_ROOT}/build-output/RExtension-test/linux
36 | PACKAGES_ROOT=${ENL_ROOT}/packages
37 |
38 | DEFAULT_R_HOME=/usr/lib/R
39 |
40 | # Find R_HOME from user, or set to default for testing.
41 | # Error code 1 is generic bash error.
42 | #
43 | if [ -z "${R_HOME}" ]; then
44 | if [ -d "${DEFAULT_R_HOME}" ]; then
45 | export R_HOME=${DEFAULT_R_HOME}
46 | else
47 | echo "R_HOME is empty"
48 | exit 1
49 | fi
50 | fi
51 |
52 | # Test in release mode if nothing is specified
53 | #
54 | if [ "$1" == "" ]; then
55 | set -- release
56 | fi
57 |
58 | while [ "$1" != "" ]; do
59 | # Advance arg passed to build.cmd
60 | build $1
61 | shift
62 | done;
63 |
--------------------------------------------------------------------------------
/language-extensions/python/src/PythonColumn.cpp:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // Copyright (C) Microsoft Corporation.
3 | // Distributed under the Boost Software License, Version 1.0.
4 | // (See accompanying file LICENSE_1_0.txt or copy at
5 | // https://www.boost.org/LICENSE_1_0.txt)
6 | //
7 | // @File: PythonColumn.cpp
8 | //
9 | // Purpose:
10 | // Encapsulate data column attributes
11 | //
12 | //*************************************************************************************************
13 |
14 | #include "PythonColumn.h"
15 |
16 | using namespace std;
17 |
18 | //-------------------------------------------------------------------------------------------------
19 | // Name: PythonColumn::PythonColumn
20 | //
21 | // Description:
22 | // Initializes the class that encapsulates one column in the Python DataFrame/Dictionary
23 | //
24 | PythonColumn::PythonColumn(
25 | const SQLCHAR *columnName,
26 | SQLSMALLINT columnNameLength,
27 | SQLSMALLINT dataType,
28 | SQLULEN columnSize,
29 | SQLSMALLINT decimalDigits,
30 | SQLSMALLINT nullable) :
31 | m_dataType(dataType),
32 | m_size(columnSize),
33 | m_decimalDigits(decimalDigits),
34 | m_nullable(nullable)
35 | {
36 | const char *name = static_cast(static_cast(columnName));
37 |
38 | // columnNameLength does not include the null terminator.
39 | //
40 | #if defined(_DEBUG)
41 | if (static_cast(columnNameLength) != strlen(name))
42 | {
43 | throw invalid_argument("Invalid column name length, it doesn't match string length.");
44 | }
45 | #endif
46 |
47 | // Store the information for this column
48 | //
49 | m_name = string(name, columnNameLength);
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/language-extensions/python/include/PythonColumn.h:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // Copyright (C) Microsoft Corporation.
3 | // Distributed under the Boost Software License, Version 1.0.
4 | // (See accompanying file LICENSE_1_0.txt or copy at
5 | // https://www.boost.org/LICENSE_1_0.txt)
6 | //
7 | // @File: PythonColumn.h
8 | //
9 | // Purpose:
10 | // Encapsulate dataset column attributes
11 | //
12 | //*************************************************************************************************
13 |
14 | #pragma once
15 | #include "Common.h"
16 |
17 | // Encapsulate column information
18 | //
19 | class PythonColumn
20 | {
21 | public:
22 | PythonColumn(
23 | const SQLCHAR *columnName,
24 | SQLSMALLINT columnNameLength,
25 | SQLSMALLINT dataType,
26 | SQLULEN columnSize,
27 | SQLSMALLINT decimalDigits,
28 | SQLSMALLINT nullable);
29 |
30 | const std::string& Name() const
31 | {
32 | return m_name;
33 | }
34 |
35 | SQLSMALLINT DataType() const
36 | {
37 | return m_dataType;
38 | }
39 |
40 | SQLULEN Size() const
41 | {
42 | return m_size;
43 | }
44 |
45 | SQLSMALLINT DecimalDigits() const
46 | {
47 | return m_decimalDigits;
48 | }
49 |
50 | SQLSMALLINT Nullable() const
51 | {
52 | return m_nullable;
53 | }
54 |
55 | protected:
56 | // Name of the column.
57 | //
58 | std::string m_name;
59 |
60 | // Data Type of the column.
61 | //
62 | SQLSMALLINT m_dataType;
63 |
64 | // Size of the column.
65 | //
66 | SQLULEN m_size;
67 |
68 | // Decimal digits of the column.
69 | //
70 | SQLSMALLINT m_decimalDigits;
71 |
72 | // The column is nullable or not.
73 | //
74 | SQLSMALLINT m_nullable;
75 | };
76 |
--------------------------------------------------------------------------------
/language-extensions/python/test/build/windows/run-pythonextension-test.cmd:
--------------------------------------------------------------------------------
1 | @ECHO off
2 | SETLOCAL
3 |
4 | REM Set environment variables
5 | REM
6 | SET ENL_ROOT=%~dp0..\..\..\..\..
7 | SET PACKAGES_ROOT=%ENL_ROOT%\packages
8 | SET PYTHONEXTENSION_TEST_WORKING_DIR=%ENL_ROOT%\build-output\pythonextension-test\windows
9 | SET PYTHONEXTENSION_WORKING_DIR=%ENL_ROOT%\build-output\pythonextension\windows
10 | SET GTEST_HOME=%PACKAGES_ROOT%\Microsoft.googletest.v140.windesktop.msvcstl.dyn.rt-dyn.1.8.1.3
11 | SET GTEST_LIB_PATH=%GTEST_HOME%\lib\native\v140\windesktop\msvcstl\dyn\rt-dyn\x64
12 |
13 | :LOOP
14 |
15 | REM Set cmake config to first arg
16 | REM
17 | SET CMAKE_CONFIGURATION=%1
18 |
19 | REM *Setting CMAKE_CONFIGURATION to anything but "debug" will set CMAKE_CONFIGURATION to "release".
20 | REM The string comparison for CMAKE_CONFIGURATION is case-insensitive.
21 | REM
22 | IF NOT DEFINED CMAKE_CONFIGURATION (SET CMAKE_CONFIGURATION=release)
23 | IF /I %CMAKE_CONFIGURATION%==debug (SET CMAKE_CONFIGURATION=debug) ELSE (SET CMAKE_CONFIGURATION=release)
24 |
25 | pushd %PYTHONEXTENSION_TEST_WORKING_DIR%\%CMAKE_CONFIGURATION%
26 | copy %PYTHONEXTENSION_WORKING_DIR%\%CMAKE_CONFIGURATION%\pythonextension.* .
27 | copy %GTEST_LIB_PATH%\%CMAKE_CONFIGURATION%\gtest* .
28 |
29 | IF "%PYTHONHOME%"=="" (SET PYTHONHOME=%PACKAGES_ROOT%\python)
30 |
31 | SET PATH=%PATH%;%PYTHONHOME%;
32 |
33 | pythonextension-test.exe --gtest_output=xml:%ENL_ROOT%\out\TestReport_PythonExtension-test.xml
34 | IF %ERRORLEVEL% NEQ 0 GOTO error
35 | popd
36 |
37 | REM Advance arg passed to build-pythonextension-test.cmd
38 | REM
39 | SHIFT
40 |
41 | REM Continue running using more configs until argv has been exhausted
42 | REM
43 | IF NOT "%~1"=="" GOTO LOOP
44 |
45 | :error
46 | EXIT /b %ERRORLEVEL%
47 |
48 | :USAGE
49 | echo.
50 | echo Usage:
51 | echo %0 { debug ^| release }
52 |
--------------------------------------------------------------------------------
/language-extensions/R/test/src/main.cpp:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // RExtension-test : Executable testing language extension that implements the SQL Server
3 | // external language communication protocol.
4 | // Copyright (C) 2020 Microsoft Corporation.
5 | //
6 | // This file is part of RExtension-test.
7 | //
8 | // RExtension-test is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // RExtension-test is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with RExtension-test. If not, see .
20 | //
21 | // @File: main.cpp
22 | //
23 | // Purpose:
24 | // Tests the RExtension's implementation of the external language APIs.
25 | //
26 | //*************************************************************************************************
27 |
28 | #include "Common.h"
29 |
30 | int g_argc = 0;
31 | const char **g_argv = nullptr;
32 |
33 | int main(int argc, const char **argv)
34 | {
35 | // Banner
36 | //
37 | std::cout << "Running RExtension C++ unit tests.\n";
38 |
39 | // First, initiate Google Test framework - this will remove
40 | // framework-specific parameters from argc and argv
41 | //
42 | ::testing::InitGoogleTest(&argc, const_cast(argv));
43 | g_argc = argc;
44 | g_argv = argv;
45 |
46 | int rc = RUN_ALL_TESTS();
47 |
48 | return rc;
49 | }
50 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/sample/regex/dotnet-core-CSharp-regex-win.sql:
--------------------------------------------------------------------------------
1 | -- Step 1: Create sample data
2 |
3 | CREATE DATABASE csharptest
4 | GO
5 | USE csharptest
6 | GO
7 |
8 | CREATE TABLE testdata (
9 | [id] int,
10 | [text] varchar(100),
11 | )
12 | GO
13 |
14 | INSERT INTO testdata(id, "text") VALUES (4, 'This sentence contains C#')
15 | INSERT INTO testdata(id, "text") VALUES (1, 'This sentence does not')
16 | INSERT INTO testdata(id, "text") VALUES (3, 'I love c#!')
17 | INSERT INTO testdata(id, "text") VALUES (2, NULL)
18 | GO
19 |
20 | -- Step 2: Create the main class
21 | -- Step 3: Compile and create a .dll file
22 |
23 | -- Step 4: Create external language
24 |
25 | CREATE EXTERNAL LANGUAGE Dotnet
26 | FROM
27 | (CONTENT = N'\build-output\dotnet-core-CSharp-extension\windows\release\packages\dotnet-core-CSharp-lang-extension.zip', FILE_NAME = 'nativecsharpextension.dll' );
28 | GO
29 |
30 | -- Step 5: Create external libraries
31 |
32 | CREATE EXTERNAL LIBRARY regex
33 | FROM (CONTENT = '\language-extensions\dotnet-core-CSharp\sample\regex\pkg\obj\Debug\RegexSample.dll')
34 | WITH (LANGUAGE = 'Dotnet');
35 | GO
36 |
37 | -- Step 6: Call the .NET Core C# class
38 |
39 | declare @rowsCount int
40 | declare @regexExpr varchar(200)
41 | set @regexExpr = N'[Cc]#'
42 |
43 | EXEC sp_execute_external_script
44 | @language = N'Dotnet'
45 | , @script = N'regex;UserExecutor.CSharpRegexExecutor'
46 | , @input_data_1 = N'SELECT * FROM testdata'
47 | , @params = N'@regexExpr varchar(200) OUTPUT, @rowsCount int OUTPUT'
48 | , @regexExpr = @regexExpr OUTPUT
49 | , @rowsCount = @rowsCount OUTPUT
50 | with result sets ((id int, text varchar(100)));
51 |
52 | select @rowsCount as rowsCount, @regexExpr as message
53 | print @rowsCount
54 | print @regexExpr
55 |
56 |
--------------------------------------------------------------------------------
/language-extensions/python/include/PythonNamespace.h:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // Copyright (C) Microsoft Corporation.
3 | // Distributed under the Boost Software License, Version 1.0.
4 | // (See accompanying file LICENSE_1_0.txt or copy at
5 | // https://www.boost.org/LICENSE_1_0.txt)
6 | //
7 | // @File: PythonNamespace.h
8 | //
9 | // Purpose:
10 | // Global class to keep the global python namespace
11 | //
12 | //*************************************************************************************************
13 |
14 | #pragma once
15 | #include "Common.h"
16 |
17 | //-------------------------------------------------------------------------------------------------
18 | // Description:
19 | // Global class storing the python namespace
20 | //
21 | class PythonNamespace
22 | {
23 | public:
24 | // Initialize this global class
25 | //
26 | static void Init();
27 |
28 | // Cleanup this global class
29 | //
30 | static void Cleanup();
31 |
32 | // Get the main python module
33 | //
34 | static boost::python::object &MainModule() { return sm_mainModule; }
35 |
36 | // Get the main python namespace
37 | //
38 | static boost::python::object& MainNamespace() { return sm_mainNamespace; }
39 |
40 | // Get the original path list
41 | //
42 | static boost::python::object& OriginalPath() { return sm_originalPath; }
43 |
44 | private:
45 | static boost::python::object sm_mainModule; // The boost python module, contains the namespace.
46 |
47 | // The underlying boost::python namespace, which contains all the python variables.
48 | // We execute any python scripts on this namespace.
49 | //
50 | static boost::python::object sm_mainNamespace;
51 |
52 | static boost::python::object sm_originalPath; // The original system python path
53 | };
54 |
--------------------------------------------------------------------------------
/language-extensions/java/src/JavaLibraryUtils.cpp:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: JavaLibraryUtils.cpp
6 | //
7 | // Purpose:
8 | // Cross-platform utility functions to handle library management for
9 | // the Java extension.
10 | //
11 | //*********************************************************************
12 | #include "JavaLibraryUtils.h"
13 | #include "JavaPathSettings.h"
14 | #include "Logger.h"
15 |
16 | using namespace std;
17 |
18 | //--------------------------------------------------------------------------------------------------
19 | // Name: JavaLibraryUtils::GetLibrariesClassPath
20 | //
21 | // Description:
22 | // Gets the string to include in the classpath for external libraries. This is done by searching
23 | // for every file under the directory and adding it to the path. This is needed, because JVM expects
24 | // that the full path for jars in the class path.
25 | //
26 | // Notes:
27 | // First private libraries are added to the classpath then public libraries.
28 | //
29 | // Returns:
30 | // The classpath of all the jars in the library management directories
31 | //
32 | string JavaLibraryUtils::GetLibrariesClassPath()
33 | {
34 | string classPath = "";
35 |
36 | // Check if private library path was sent from SQL Server.
37 | //
38 | const string & privateLibraryPath = JavaPathSettings::GetPrivateLibraryPath();
39 |
40 | if (!privateLibraryPath.empty())
41 | {
42 | FindAppendFileNames(privateLibraryPath, classPath);
43 | }
44 |
45 | // Check if the public library path was sent from SQL Server.
46 | //
47 | const string & publicLibraryPath = JavaPathSettings::GetPublicLibraryPath();
48 |
49 | if (!publicLibraryPath.empty())
50 | {
51 | FindAppendFileNames(publicLibraryPath, classPath);
52 | }
53 |
54 | return classPath;
55 | }
56 |
--------------------------------------------------------------------------------
/language-extensions/R/include/Common.h:
--------------------------------------------------------------------------------
1 | //**************************************************************************************************
2 | // RExtension : A language extension implementing the SQL Server
3 | // external language communication protocol for R.
4 | // Copyright (C) 2020 Microsoft Corporation.
5 | //
6 | // This file is part of RExtension.
7 | //
8 | // RExtension is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // RExtension is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with RExtension. If not, see .
20 | //
21 | // @File: Common.h
22 | //
23 | // Purpose:
24 | // Common headers for RExtension.
25 | //
26 | //**************************************************************************************************
27 |
28 | #pragma once
29 |
30 | #ifdef _WIN64
31 | #include
32 | #endif
33 |
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 | #include
40 | #include
41 |
42 | // Before including Rcpp headers, undefine ERROR if it is defined already since
43 | // R_ext/RS.h defines ERROR and we want to avoid redefinition warnings.
44 | //
45 | #ifdef ERROR
46 | #undef ERROR
47 | #endif
48 | #include "Rcpp.h"
49 | #include "RInside.h" // for the embedded R via RInside
50 |
51 | #include "Logger.h"
52 | #include "REnvironment.h"
53 | #include "RPathSettings.h"
54 | #include "Utilities.h"
55 |
--------------------------------------------------------------------------------
/language-extensions/python/include/PythonPathSettings.h:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // Copyright (C) Microsoft Corporation.
3 | // Distributed under the Boost Software License, Version 1.0.
4 | // (See accompanying file LICENSE_1_0.txt or copy at
5 | // https://www.boost.org/LICENSE_1_0.txt)
6 | //
7 | // @File: PythonPathSettings.h
8 | //
9 | // Purpose:
10 | // Global class to keep language runtime settings
11 | //
12 | //*************************************************************************************************
13 |
14 | #pragma once
15 | #include "Common.h"
16 |
17 | //-------------------------------------------------------------------------------------------------
18 | // Description:
19 | // Global class storing the language runtime paths and parameters
20 | //
21 | class PythonPathSettings
22 | {
23 | public:
24 | // Initialize this global class
25 | //
26 | static void Init(
27 | const SQLCHAR *languageParams,
28 | const SQLCHAR *languagePath,
29 | const SQLCHAR *publicLibraryPath,
30 | const SQLCHAR *privateLibraryPath);
31 |
32 | // Get the private library path sent by SQL Server
33 | //
34 | static const std::string& PrivateLibraryPath() { return sm_privateLibraryPath; }
35 |
36 | // Get the public library path sent by SQL Server
37 | //
38 | static const std::string& PublicLibraryPath() { return sm_publicLibraryPath; }
39 |
40 | // Get the extension root folder
41 | //
42 | static const std::string& RootPath() { return sm_languagePath; }
43 |
44 | // Get the language parameters sent by SQL Server
45 | //
46 | static const std::string& Params() { return sm_languageParams; }
47 |
48 | private:
49 | static std::string sm_languagePath;
50 | static std::string sm_languageParams;
51 | static std::string sm_privateLibraryPath;
52 | static std::string sm_publicLibraryPath;
53 | };
54 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/src/managed/CSharpColumn.cs:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: CSharpColumn.cs
6 | //
7 | // Purpose:
8 | // Encapsulate data column attributes
9 | //
10 | //*********************************************************************
11 | using System;
12 | using System.Collections.Generic;
13 | using static Microsoft.SqlServer.CSharpExtension.Sql;
14 |
15 | namespace Microsoft.SqlServer.CSharpExtension
16 | {
17 | ///
18 | /// This class stores column meta data
19 | ///
20 | public class CSharpColumn
21 | {
22 | ///
23 | /// An integer identifying the index of this column.
24 | /// Columns are numbered sequentially in increasing order starting at 0.
25 | ///
26 | public ushort Id { get; set; }
27 |
28 | ///
29 | /// The name of this column.
30 | ///
31 | public string Name { get; set; }
32 |
33 | ///
34 | /// The maximum size in bytes of the underlying data in this column.
35 | ///
36 | public ulong Size { get; set; }
37 |
38 | ///
39 | /// The Sql data type of this column.
40 | ///
41 | public SqlDataType DataType { get; set; }
42 |
43 | ///
44 | /// A value that indicates whether this column may contain NULL values.
45 | /// SQL_NO_NULLS(0): The column cannot contain NULL values.
46 | /// SQL_NULLABLE(1): The column may contain NULL values.
47 | ///
48 | public short Nullable { get; set; }
49 |
50 | ///
51 | /// The decimal digits of underlying data in this column.
52 | ///
53 | public short DecimalDigits { get; set; }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/language-extensions/java/src/Logger.cpp:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: Logger.cpp
6 | //
7 | // Purpose:
8 | // Implementation of logging for the java extension.
9 | //
10 | //*********************************************************************
11 | #include "Logger.h"
12 | #include
13 | #include
14 |
15 | using namespace std;
16 |
17 | //---------------------------------------------------------------------
18 | // Name: LogError
19 | //
20 | // Description:
21 | // Log an error to stderr with format "TIMESTAMP Error: ".
22 | //
23 | void Logger::LogError(const string &errorMsg)
24 | {
25 | cerr << GetCurrentTimestamp() << "Error: " << errorMsg << endl;
26 | }
27 |
28 | //---------------------------------------------------------------------
29 | // Name: LogJavaException
30 | //
31 | // Description:
32 | // Log a c++ exception to stderr with format "TIMESTAMP Exception
33 | // occurred: ".
34 | //
35 | void Logger::LogException(const exception &e)
36 | {
37 | cerr << GetCurrentTimestamp() << "Exception occurred: " << e.what() << endl;
38 | }
39 |
40 | //---------------------------------------------------------------------
41 | // Name: LogJavaException
42 | //
43 | // Description:
44 | // Log a java exception to stderr with format "TIMESTAMP Exception
45 | // thrown in Java: ".
46 | //
47 | void Logger::LogJavaException(const string &exceptionMsg)
48 | {
49 | cerr << GetCurrentTimestamp() << "Exception occurred in Java: " << exceptionMsg << endl;
50 | }
51 |
52 | //---------------------------------------------------------------------
53 | // Name: Log
54 | //
55 | // Description:
56 | // Log a message to stdout with format "TIMESTAMP ".
57 | //
58 | void Logger::Log(const string &msg)
59 | {
60 | #ifdef DEBUG
61 | cout << GetCurrentTimestamp() << msg << endl;
62 | #endif
63 | }
64 |
--------------------------------------------------------------------------------
/language-extensions/java/src/linux/JavaLibraryUtils_linux.cpp:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: JavaLibraryUtils_linux.cpp
6 | //
7 | // Purpose:
8 | // Linux specific utility functions to handle library management
9 | // for the Java extension.
10 | //
11 | //*********************************************************************
12 | #include "JavaLibraryUtils.h"
13 | #include "JavaExtensionUtils.h"
14 | #include "Logger.h"
15 | #include
16 | #include
17 |
18 | using namespace std;
19 |
20 | //----------------------------------------------------------------------------
21 | // Name: JavaLibraryUtils::AppendFileNames
22 | //
23 | // Description:
24 | // Finds all files under the base directory and appends them to the output.
25 | //
26 | // Notes:
27 | // This function will silently fail if an error occurs, this is expected
28 | // because the query should attempt to continue.
29 | //
30 | // Returns:
31 | // none
32 | //
33 | void JavaLibraryUtils::FindAppendFileNames(const string &basePath, string &output)
34 | {
35 | DIR *directory = nullptr;
36 | struct dirent *entry = nullptr;
37 |
38 | directory = opendir(basePath.c_str());
39 | if (directory != nullptr)
40 | {
41 | entry = readdir(directory);
42 | while (entry != nullptr)
43 | {
44 | string fileName = string(entry->d_name);
45 |
46 | if (fileName.compare("..") != 0 && fileName.compare(".") != 0)
47 | {
48 | // Add the separator if needed.
49 | //
50 | if (!output.empty())
51 | {
52 | output += JavaExtensionUtils::GetClassPathSeparator();
53 | }
54 |
55 | output += basePath + "/" + fileName;
56 | }
57 |
58 | // Get next entry
59 | //
60 | entry = readdir(directory);
61 | }
62 |
63 | closedir(directory);
64 | }
65 | else
66 | {
67 | string msg = "Error opening library directory " + basePath;
68 | LOG_ERROR(msg);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/language-extensions/python/include/PythonExtensionUtils.h:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // Copyright (C) Microsoft Corporation.
3 | // Distributed under the Boost Software License, Version 1.0.
4 | // (See accompanying file LICENSE_1_0.txt or copy at
5 | // https://www.boost.org/LICENSE_1_0.txt)
6 | //
7 | // @File: PythonExtensionUtils.h
8 | //
9 | // Purpose:
10 | // Platform specific utility functions for Python Extension
11 | //
12 | //*************************************************************************************************
13 |
14 | #pragma once
15 | #include "Common.h"
16 | #include
17 |
18 | class PythonExtensionUtils
19 | {
20 | public:
21 |
22 | // Parses the value of the active python exception
23 | // Type, value, and traceback are in separate pointers
24 | //
25 | static std::string ParsePythonException();
26 |
27 | // Extract the string from a boost::python object or PyObject*
28 | //
29 | static std::string ExtractString(PyObject *pObj);
30 | static std::string ExtractString(boost::python::object handle);
31 |
32 | // Get the value of an environment variable
33 | //
34 | static std::string GetEnvVariable(const std::string &envVarName);
35 |
36 | // Normalize path strings from \ to /
37 | //
38 | static std::string NormalizePathString(std::string pathString);
39 |
40 | // Check if bitValue is True or not
41 | //
42 | static bool IsBitTrue(SQLCHAR bitValue);
43 |
44 | // Converts a SQLGUID to a string
45 | //
46 | static std::string ConvertGuidToString(const SQLGUID *guid);
47 |
48 | // Close an open dll handle
49 | //
50 | static void FreeDLL(void *pDll);
51 |
52 | // Get the path to the python executable
53 | //
54 | static std::string GetPathToPython();
55 |
56 | // Map to store the ODBC C type to null value mapping
57 | //
58 | static const std::unordered_map sm_DataTypeToNullMap;
59 | };
60 |
--------------------------------------------------------------------------------
/language-extensions/python/test/build/linux/run-pythonextension-test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | function check_exit_code {
4 | EXIT_CODE=$?
5 | if [ ${EXIT_CODE} -eq 0 ]; then
6 | echo $1
7 | else
8 | echo $2
9 | exit ${EXIT_CODE}
10 | fi
11 | }
12 |
13 | function build {
14 | # Set cmake config to first arg
15 | #
16 | CMAKE_CONFIGURATION=$1
17 | if [ -z "${CMAKE_CONFIGURATION}" ]; then
18 | CMAKE_CONFIGURATION=release
19 | fi
20 |
21 | pushd ${PYTHONEXTENSIONTEST_WORKING_DIR}/${CMAKE_CONFIGURATION}
22 |
23 | # Move the generated libs to configuration folder
24 | #
25 | cp ${PYTHONEXTENSION_WORKING_DIR}/${CMAKE_CONFIGURATION}/libPythonExtension.so.1.2 .
26 | cp /usr/src/gtest/*.so .
27 |
28 | ENL_ROOT=${ENL_ROOT} ./pythonextension-test --gtest_output=xml:${ENL_ROOT}/out/TestReport_PythonExtension-test.xml
29 |
30 | # Check the exit code of the tests.
31 | #
32 | check_exit_code "Success: Ran pythonextension-test" "Error: pythonextension-test failed"
33 |
34 | popd
35 | }
36 |
37 | # Enlistment root and location of pythonextension-test
38 | #
39 | SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
40 | ENL_ROOT=${SCRIPTDIR}/../../../../..
41 | PYTHONEXTENSION_WORKING_DIR=${ENL_ROOT}/build-output/pythonextension/linux
42 | PYTHONEXTENSIONTEST_WORKING_DIR=${ENL_ROOT}/build-output/pythonextension-test/linux
43 | PACKAGES_ROOT=${ENL_ROOT}/packages
44 | DEFAULT_PYTHONHOME=/usr
45 |
46 | # Find PYTHONHOME from user, or set to default for tests.
47 | # Error code 1 is generic bash error.
48 | #
49 | if [ -z "${PYTHONHOME}" ]; then
50 | if [ -x "${DEFAULT_PYTHONHOME}" ]; then
51 | PYTHONHOME=${DEFAULT_PYTHONHOME}
52 | else
53 | echo "PYTHONHOME is empty"
54 | exit 1
55 | fi
56 | fi
57 |
58 | echo "Python home is ${PYTHONHOME}"
59 |
60 | # Build in release mode if nothing is specified
61 | #
62 | if [ "$1" == "" ]; then
63 | set -- release
64 | fi
65 |
66 | while [ "$1" != "" ]; do
67 | # Advance arg passed to build.cmd
68 | #
69 | build $1
70 | shift
71 | done;
72 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/src/managed/sdk/AbstractSqlServerExtensionExecutor.cs:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: AbstractSqlServerExtensionExecutor.cs
6 | //
7 | // Purpose:
8 | // Abstract class containing interface used by the .NET Core C# extension
9 | //
10 | //*********************************************************************
11 | using System.Collections.Generic;
12 | using Microsoft.Data.Analysis;
13 |
14 | namespace Microsoft.SqlServer.CSharpExtension.SDK
15 | {
16 | ///
17 | /// Abstract class containing interface used by the .NET Core C# extension
18 | ///
19 | public abstract class AbstractSqlServerExtensionExecutor
20 | {
21 | ///
22 | /// Supported versions of the .NET Core C# extension
23 | ///
24 | public readonly int SQLSERVER_DOTNET_LANG_EXTENSION_V1 = 1;
25 |
26 | ///
27 | /// Default constructor for AbstractSqlServerExtensionExecutor
28 | ///
29 | public AbstractSqlServerExtensionExecutor() {}
30 |
31 | ///
32 | /// Default implementation of init() is no-op
33 | ///
34 | public virtual void Init(string sessionId, int taskId, int numTasks) {}
35 |
36 | ///
37 | /// User execute method
38 | ///
39 | ///
40 | /// A Dataframe containing all the input columns
41 | ///
42 | ///
43 | /// A Dictionary containing all the parameters with name as the key
44 | ///
45 | public abstract DataFrame Execute(DataFrame input, Dictionary sqlParams);
46 |
47 | ///
48 | /// Default implementation of cleanup() is no-op
49 | ///
50 | public virtual void Cleanup() {}
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/language-extensions/R/test/include/Common.h:
--------------------------------------------------------------------------------
1 | //**************************************************************************************************
2 | // RExtension-test : Executable testing language extension that implements the SQL Server
3 | // external language communication protocol.
4 | // Copyright (C) 2020 Microsoft Corporation.
5 |
6 | // This file is part of RExtension-test.
7 |
8 | // RExtension-test is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 |
13 | // RExtension-test is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 |
18 | // You should have received a copy of the GNU General Public License
19 | // along with RExtension-test. If not, see .
20 |
21 | // @File: Common.h
22 | //
23 | // Purpose:
24 | // Common headers for RExtenion-test.
25 | //
26 | //**************************************************************************************************
27 |
28 | #pragma once
29 |
30 | #ifdef _WIN64
31 | #include
32 | #include
33 | #else
34 | #include
35 | #include
36 | #endif
37 |
38 | #include
39 | #include
40 | #include
41 | #include
42 | #include
43 | #include
44 |
45 | #include "gtest/gtest.h"
46 |
47 | // Before including Rcpp headers, undefine ERROR if it is defined already since
48 | // R_ext/RS.h defines ERROR and we want to avoid redefinition warnings.
49 | //
50 | #ifdef ERROR
51 | #undef ERROR
52 | #endif
53 | #include "Rcpp.h"
54 | #include "RInside.h"
55 |
56 | #define TOTAL_NUMBER_OF_TEST_SUITES 2
57 |
58 | #include "RExtensionApiTests.h"
59 | #include "Unicode.h"
60 | #include "Utilities.h"
61 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/src/managed/utils/DataSetUtils.cs:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: DataSetUtils.cs
6 | //
7 | // Purpose:
8 | // Provides methods needed for Input/Output DataSet
9 | //
10 | //*********************************************************************
11 | using System;
12 |
13 | namespace Microsoft.SqlServer.CSharpExtension
14 | {
15 | ///
16 | /// This class contains methods needed for Input/Output DataSet
17 | ///
18 | internal class DataSetUtils
19 | {
20 | ///
21 | /// This method splits a string to an array of substring according to lengths.
22 | ///
23 | ///
24 | /// The string to be split
25 | ///
26 | ///
27 | /// An array of integers representing the lengths
28 | ///
29 | public static string[] StringSplitToArray(string str, int[] strLens)
30 | {
31 | string[] strArray = new string[strLens.Length];
32 |
33 | // Return empty string list if the string is null
34 | //
35 | if(str == null)
36 | {
37 | return strArray;
38 | }
39 |
40 | int startIndex = 0;
41 | for (int i = 0; i < strLens.Length; ++i)
42 | {
43 | if(strLens[i] == -1)
44 | {
45 | strArray[i] = null;
46 | continue;
47 | }
48 |
49 | if(startIndex + strLens[i] > str.Length)
50 | {
51 | strArray[i] = str.Substring(startIndex);
52 | break;
53 | }
54 |
55 | strArray[i] = str.Substring(startIndex, strLens[i]);
56 | startIndex += strLens[i];
57 | }
58 |
59 | return strArray;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/language-extensions/R/test/build/windows/run-RExtension-test.cmd:
--------------------------------------------------------------------------------
1 | @ECHO off
2 | SETLOCAL
3 |
4 | REM Set environment variables
5 | REM
6 | SET ENL_ROOT=%~dp0..\..\..\..\..
7 | SET REXTENSIONTEST_WORKING_DIR=%ENL_ROOT%\build-output\RExtension-test\windows
8 | SET REXTENSION_WORKING_DIR=%ENL_ROOT%\build-output\RExtension\windows
9 | SET PACKAGES_ROOT=%ENL_ROOT%\packages
10 | SET GTEST_HOME=%PACKAGES_ROOT%\Microsoft.googletest.v140.windesktop.msvcstl.dyn.rt-dyn.1.8.1.3
11 | SET GTEST_LIB_PATH=%GTEST_HOME%\lib\native\v140\windesktop\msvcstl\dyn\rt-dyn\x64
12 |
13 | SET DEFAULT_R_HOME=%PACKAGES_ROOT%\R-4.0.5-win
14 |
15 | REM Find R_HOME from user, or set to default.
16 | REM Error code 203 is ENVVAR_NOT_FOUND.
17 | REM
18 | SET ENVVAR_NOT_FOUND=203
19 |
20 | IF "%R_HOME%" == "" (
21 | IF EXIST %DEFAULT_R_HOME% (
22 | SET R_HOME=%DEFAULT_R_HOME%
23 | ) ELSE (
24 | CALL :CHECKERROR %ENVVAR_NOT_FOUND% "Error: R_HOME variable must be set to run RExtension-test" || EXIT /b %ENVVAR_NOT_FOUND%
25 | )
26 | )
27 |
28 | :LOOP
29 |
30 | REM Set cmake config to first arg
31 | REM
32 | SET CMAKE_CONFIGURATION=%1
33 |
34 | REM *Setting CMAKE_CONFIGURATION to anything but "debug" will set MSVC_BUILD_CONFIGURATION to "release".
35 | REM The string comparison for CMAKE_CONFIGURATION is case-insensitive.
36 | REM
37 | IF NOT DEFINED CMAKE_CONFIGURATION (SET CMAKE_CONFIGURATION=release)
38 | IF /I %CMAKE_CONFIGURATION%==debug (SET MSVC_BUILD_CONFIGURATION=debug) ELSE (SET MSVC_BUILD_CONFIGURATION=release)
39 |
40 | pushd %REXTENSIONTEST_WORKING_DIR%\%MSVC_BUILD_CONFIGURATION%
41 | copy %REXTENSION_WORKING_DIR%\%MSVC_BUILD_CONFIGURATION%\libRExtension.dll .
42 | copy %GTEST_LIB_PATH%\debug\gtest.dll .
43 | SET PATH=%R_HOME%\bin\x64;%PATH%
44 | RExtension-test.exe --gtest_output=xml:%ENL_ROOT%\out\TestReport_RExtension-test.xml
45 | IF %ERRORLEVEL% NEQ 0 GOTO error
46 | popd
47 |
48 | REM Advance arg passed to build-RExtension-test.cmd
49 | REM
50 | SHIFT
51 |
52 | REM Continue running using more configs until argv has been exhausted
53 | REM
54 | IF NOT "%~1"=="" GOTO LOOP
55 |
56 | :error
57 | EXIT /b %ERRORLEVEL%
58 |
59 | :USAGE
60 | echo.
61 | echo Usage:
62 | echo %0 { debug ^| release }
63 |
--------------------------------------------------------------------------------
/language-extensions/java/src/windows/JavaLibraryUtils_win.cpp:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: JavaLibraryUtils_win.cpp
6 | //
7 | // Purpose:
8 | // Windows specific utility functions to handle library management
9 | // for the Java extension.
10 | //
11 | //*********************************************************************
12 | #include "JavaLibraryUtils.h"
13 | #include "JavaExtensionUtils.h"
14 |
15 | using namespace std;
16 |
17 | //----------------------------------------------------------------------------
18 | // Name: JavaLibraryUtils::AppendFileNames
19 | //
20 | // Description:
21 | // Finds all files under the base directory and appends them to the output.
22 | //
23 | // Notes:
24 | // This function will silently fail if an error occurs, this is expected
25 | // because the query should attempt to continue.
26 | //
27 | // Returns:
28 | // none
29 | //
30 | void JavaLibraryUtils::FindAppendFileNames(const string &basePath, string &output)
31 | {
32 | // String to indicate we should find all files under this directory
33 | //
34 | string wildCard = basePath + "\\*";
35 |
36 | HRESULT hr = S_OK;
37 | WIN32_FIND_DATAA ffa;
38 | HANDLE hFind = INVALID_HANDLE_VALUE;
39 |
40 | // Find the first file in the directory.
41 | //
42 | if (SUCCEEDED(hr))
43 | {
44 | hFind = FindFirstFileA(wildCard.c_str(), &ffa);
45 | if (INVALID_HANDLE_VALUE == hFind)
46 | {
47 | hr = HRESULT_FROM_WIN32(GetLastError());
48 | }
49 | }
50 |
51 | // Loop through each file in the folder which represents a library, and delete it.
52 | //
53 | if (SUCCEEDED(hr))
54 | {
55 | do
56 | {
57 | // Skip over the entry for the current directory
58 | //
59 | if (ffa.cFileName[0] == '.')
60 | {
61 | continue;
62 | }
63 |
64 | // Add the separator if needed.
65 | //
66 | if (!output.empty())
67 | {
68 | output += JavaExtensionUtils::GetClassPathSeparator();
69 | }
70 |
71 | output += basePath + "\\" + string(ffa.cFileName);
72 | } while (FindNextFileA(hFind, &ffa) != 0);
73 |
74 | FindClose(hFind);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/build/windows/create-dotnet-core-CSharp-extension-zip.cmd:
--------------------------------------------------------------------------------
1 | @ECHO off
2 | SETLOCAL
3 |
4 | SET ENL_ROOT=%~dp0..\..\..\..
5 | SET DOTNET_EXTENSION_WORKING_DIR=%ENL_ROOT%\build-output\dotnet-core-CSharp-extension\windows
6 |
7 | :LOOP
8 |
9 | REM Set build config to first arg
10 | REM
11 | SET BUILD_CONFIGURATION=%1
12 |
13 | REM Setting BUILD_CONFIGURATION to anything but "debug" will set BUILD_CONFIGURATION to "release".
14 | REM The string comparison for BUILD_CONFIGURATION is case-insensitive.
15 | REM
16 | IF NOT DEFINED BUILD_CONFIGURATION (SET BUILD_CONFIGURATION=release)
17 | IF /I NOT %BUILD_CONFIGURATION%==debug (SET BUILD_CONFIGURATION=release)
18 |
19 | SET BUILD_OUTPUT=%DOTNET_EXTENSION_WORKING_DIR%\%BUILD_CONFIGURATION%
20 |
21 | MKDIR %BUILD_OUTPUT%\packages
22 |
23 | REM Delete the ref folder so that the zip can be loaded by the SPEES
24 | REM
25 | RD /S /Q %BUILD_OUTPUT%\ref
26 | POPD
27 |
28 | REM Define files to compress, conditionally including .pdb files if BUILD_CONFIGURATION is "debug"
29 | REM
30 | SET FILES_TO_COMPRESS=%BUILD_OUTPUT%\*.dll, %BUILD_OUTPUT%\Microsoft.SqlServer.CSharpExtension.runtimeconfig.json, %BUILD_OUTPUT%\Microsoft.SqlServer.CSharpExtension.deps.json
31 | IF /I "%BUILD_CONFIGURATION%"=="debug" (SET FILES_TO_COMPRESS=%FILES_TO_COMPRESS%, %BUILD_OUTPUT%\*.pdb)
32 |
33 | REM Package the signed binaries.
34 | REM
35 | powershell -NoProfile -ExecutionPolicy Unrestricted ^
36 | -Command "Compress-Archive -Force -Path %FILES_TO_COMPRESS%" ^
37 | "-DestinationPath %BUILD_OUTPUT%\packages\dotnet-core-CSharp-lang-extension.zip"
38 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to create zip for dotnet-core-CSharp-extension for configuration=%BUILD_CONFIGURATION%" || EXIT /b %ERRORLEVEL%
39 |
40 | ECHO "Success: Compressed dotnet-core-CSharp-extension for %BUILD_CONFIGURATION% configuration."
41 |
42 | REM Advance arg passed to create-dotnet-core-CSharp-extension-zip.cmd
43 | REM
44 | SHIFT
45 | REM Continue building using more configs until argv has been exhausted
46 | REM
47 | IF NOT "%~1"=="" GOTO LOOP
48 |
49 | EXIT /b %ERRORLEVEL%
50 |
51 | :CHECKERROR
52 | IF %1 NEQ 0 (
53 | ECHO %2
54 | EXIT /b %1
55 | )
56 | EXIT /b 0
57 |
--------------------------------------------------------------------------------
/language-extensions/java/samples/regex/readme.md:
--------------------------------------------------------------------------------
1 | # Regex sample
2 |
3 | This sample shows you how to use SQL Server Language Extensions to create a Java program that receives two columns (ID and text) from SQL Server and a regular expression as an input parameter. The class returns two columns back to SQL Server (ID and text).
4 |
5 | For a given text in the text column sent to the Java program, the code checks if the given regular expression is fulfilled, and if it is fulfilled, it returns that text together with the original ID.
6 |
7 | This particular sample uses a regular expression that checks if a text contains the word "Java" or "java".
8 |
9 | ## Sample files
10 |
11 | * RegexSample.Java - This is the class containing the Java code that will be invoked from SQL Server
12 | * java-regex-linux.sql and java-regex-win.sql - SQL file containing T-SQL script for configuring and creating test data and calling the Java sample program.
13 |
14 | ## Prerequisites
15 |
16 | + SQL Server 2019 Database Engine instance with the extensibility framework and Java programming extension. [Installation guide](https://docs.microsoft.com/en-us/sql/language-extensions/install/install-sql-server-language-extensions-on-windows?view=sqlallproducts-allversions).
17 |
18 | + SQL Server Management Studio or Azure Data Studio for executing T-SQL.
19 |
20 | + Java SE Development Kit (JDK) 8 or JRE 8 on Windows or Linux.
21 |
22 | + Command-line compilation using **javac** is sufficient for this sample.
23 |
24 | ### Compiling a class file
25 |
26 | The class file can be created using the command-line compiler **javac**. For this sample, create a folder containing the RegexSample.java file.
27 |
28 | To create the class files, navigate to the folder containing your java file and run this command:
29 |
30 | ```cmd
31 | javac -cp *.java
32 | ```
33 |
34 | ### Creating a jar file
35 |
36 | When using this sample and executing a Java code from SQL Server, we recommend packaging your class files into a jar file.
37 |
38 | To create a jar from class files, navigate to the parent folder of the location that contains the class file and run this command:
39 |
40 | ```cmd
41 | jar -cf folder/*.class
42 | ```
43 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/src/managed/CSharpParam.cs:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: CSharpParam.cs
6 | //
7 | // Purpose:
8 | // Classes storing information about input/output parameter.
9 | //
10 | //*********************************************************************
11 | using System;
12 | using System.Collections.Generic;
13 | using static Microsoft.SqlServer.CSharpExtension.Sql;
14 |
15 | namespace Microsoft.SqlServer.CSharpExtension
16 | {
17 | ///
18 | /// This class stores input/output parameter.
19 | ///
20 | public class CSharpParam
21 | {
22 | ///
23 | /// An integer identifying the index of this parameter.
24 | ///
25 | public ushort Number { get; set; }
26 |
27 | ///
28 | /// Null-terminated UTF-8 string containing the parameter's name.
29 | ///
30 | public string Name { get; set; }
31 |
32 | ///
33 | /// The maximum size in bytes of the underlying data in this parameter.
34 | ///
35 | public ulong Size { get; set; }
36 |
37 | ///
38 | /// The Sql data type identifying this parameter's data type.
39 | ///
40 | public SqlDataType DataType { get; set; }
41 |
42 | ///
43 | /// The parameter's value.
44 | ///
45 | public dynamic Value { get; set; }
46 |
47 | ///
48 | /// The decimal digits of underlying data in this parameter
49 | ///
50 | public short DecimalDigits { get; set; }
51 |
52 | ///
53 | /// An integer value indicating the length in bytes
54 | /// of ParamValue, or SQL_NULL_DATA(-1) to indicate that the data is NULL.
55 | ///
56 | public int StrLenOrNullMap { get; set; }
57 |
58 | ///
59 | /// The type of the parameter.
60 | ///
61 | public short InputOutputType { get; set; }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/language-extensions/python/src/PythonPathSettings.cpp:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // Copyright (C) Microsoft Corporation.
3 | // Distributed under the Boost Software License, Version 1.0.
4 | // (See accompanying file LICENSE_1_0.txt or copy at
5 | // https://www.boost.org/LICENSE_1_0.txt)
6 | //
7 | // @File: PythonPathSettings.cpp
8 | //
9 | // Purpose:
10 | // Global class to keep language runtime settings
11 | //
12 | //*************************************************************************************************
13 |
14 | #include "PythonPathSettings.h"
15 | #include "PythonExtensionUtils.h"
16 |
17 | //-------------------------------------------------------------------------------------------------
18 | // Name: PythonPathSettings::Init
19 | //
20 | // Description:
21 | // Initialize the class
22 | //
23 | void
24 | PythonPathSettings::Init(
25 | const SQLCHAR *languageParams,
26 | const SQLCHAR *languagePath,
27 | const SQLCHAR *publicLibraryPath,
28 | const SQLCHAR *privateLibraryPath)
29 | {
30 | // nullptrs are mapped to empty strings - has the same effect when
31 | // the paths are used and avoids an additional flag.
32 | //
33 | sm_languageParams =
34 | (languageParams == nullptr) ? "" : reinterpret_cast(languageParams);
35 |
36 | sm_languagePath =
37 | (languagePath == nullptr) ? "" : reinterpret_cast(languagePath);
38 |
39 | sm_publicLibraryPath =
40 | (publicLibraryPath == nullptr) ? "" : reinterpret_cast(publicLibraryPath);
41 |
42 | sm_privateLibraryPath =
43 | (privateLibraryPath == nullptr) ? "" : reinterpret_cast(privateLibraryPath);
44 |
45 | // Remove single slashes and replace with forward slashes in the paths
46 | //
47 | sm_languagePath = PythonExtensionUtils::NormalizePathString(sm_languagePath);
48 | sm_privateLibraryPath = PythonExtensionUtils::NormalizePathString(sm_privateLibraryPath);
49 | sm_publicLibraryPath = PythonExtensionUtils::NormalizePathString(sm_publicLibraryPath);
50 | }
51 |
52 | std::string PythonPathSettings::sm_languageParams;
53 | std::string PythonPathSettings::sm_languagePath;
54 | std::string PythonPathSettings::sm_privateLibraryPath;
55 | std::string PythonPathSettings::sm_publicLibraryPath;
56 |
--------------------------------------------------------------------------------
/language-extensions/R/include/Logger.h:
--------------------------------------------------------------------------------
1 | //**************************************************************************************************
2 | // RExtension : A language extension implementing the SQL Server
3 | // external language communication protocol for R.
4 | // Copyright (C) 2020 Microsoft Corporation.
5 | //
6 | // This file is part of RExtension.
7 | //
8 | // RExtension is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // RExtension is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with RExtension. If not, see .
20 | //
21 | // @File: Logger.h
22 | //
23 | // Purpose:
24 | // Wrapper class around logging to standardize logging messages and errors.
25 | //
26 | //**************************************************************************************************
27 |
28 | #pragma once
29 |
30 | #define LOG(msg) Logger::Log(msg)
31 | #define LOG_ERROR(msg) Logger::LogError(msg)
32 | #define LOG_EXCEPTION(e) Logger::LogException(e)
33 |
34 | class Logger
35 | {
36 | public:
37 |
38 | // Logs an error to stderr
39 | //
40 | static void LogError(const std::string &errorMsg);
41 |
42 | // Logs an extension exception to stderr
43 | //
44 | static void LogException(const std::exception &e);
45 |
46 | // Logs a message to stdout
47 | //
48 | static void Log(const std::string &errorMsg);
49 |
50 | // Logs an R variable using R's print function
51 | //
52 | static void LogRVariable(const std::string &name);
53 |
54 | private:
55 |
56 | // Logs the message to stderr
57 | //
58 | static void LogToStdErr(const std::string &errorMsgWithTimestamp);
59 |
60 | // Gets a string of the current timestamp in the same format
61 | // of SQL format
62 | //
63 | static const char* GetCurrentTimestamp();
64 |
65 | // Buffer to hold the timestamp string.
66 | //
67 | static char sm_timestampBuffer[];
68 | };
69 |
--------------------------------------------------------------------------------
/language-extensions/java/src/JniHelper.cpp:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: JniHelper.cpp
6 | //
7 | // Purpose:
8 | // Wrappers around commonly used JNI functions
9 | //
10 | //*********************************************************************
11 | #include "JniHelper.h"
12 | #include "Logger.h"
13 |
14 | using namespace std;
15 |
16 | //--------------------------------------------------------------------------------------------------
17 | // Name: JniHelper::ThrownOnJavaException
18 | //
19 | // Description:
20 | // Throw exception when a Java exception has occurred.
21 | //
22 | void JniHelper::ThrowOnJavaException(JNIEnv *env)
23 | {
24 | ThrowOnJavaException(env, "");
25 | }
26 |
27 | //--------------------------------------------------------------------------------------------------
28 | // Name: JniHelper::ThrownOnJavaException
29 | //
30 | // Description:
31 | // Throw exception with the provided error message when a Java exception has occurred.
32 | //
33 | void JniHelper::ThrowOnJavaException(JNIEnv *env, string &&errorMsg)
34 | {
35 | jboolean isException = env->ExceptionCheck();
36 |
37 | if (isException == JNI_TRUE)
38 | {
39 | throw java_exception_error(errorMsg);
40 | }
41 | }
42 |
43 | //--------------------------------------------------------------------------------------------------
44 | // Name: JniHelper::LogJavaException
45 | //
46 | // Description:
47 | // Logs the Java exception if one has occurred
48 | //
49 | void JniHelper::LogJavaException(JNIEnv *env)
50 | {
51 | jboolean isException = env->ExceptionCheck();
52 |
53 | if (isException == JNI_TRUE)
54 | {
55 | env->ExceptionDescribe();
56 | env->ExceptionClear();
57 | }
58 | }
59 |
60 | //--------------------------------------------------------------------------------------------------
61 | // Name: JniHelper::FindMethod
62 | //
63 | // Description:
64 | // Attempts to finds a Java method through JNI
65 | //
66 | jmethodID JniHelper::FindMethod(
67 | JNIEnv *env,
68 | jclass jClass,
69 | const string &funcName,
70 | const string &funcSignature)
71 | {
72 | jmethodID result = env->GetMethodID(
73 | jClass,
74 | funcName.c_str(),
75 | funcSignature.c_str());
76 |
77 | ThrowOnJavaException(env);
78 |
79 | return result;
80 | }
81 |
--------------------------------------------------------------------------------
/language-extensions/R/build/linux/restore-packages.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | function check_exit_code {
4 | EXIT_CODE=$?
5 | if [ ${EXIT_CODE} -eq 0 ]; then
6 | echo $1
7 | else
8 | echo $2
9 | exit ${EXIT_CODE}
10 | fi
11 | }
12 |
13 | export DEBIAN_FRONTEND=noninteractive
14 | apt-get update
15 | apt-get --no-install-recommends -y install curl zip unzip apt-transport-https libstdc++6
16 |
17 | # Install development libraries needed for R extension compilation
18 | apt-get --no-install-recommends -y install libpcre3-dev liblzma-dev libbz2-dev zlib1g-dev
19 |
20 | # Add R CRAN repository.
21 | #
22 | LSB_RELEASE=$(lsb_release -cs)
23 | curl -fsSL https://cloud.r-project.org/bin/linux/ubuntu/marutter_pubkey.asc | gpg --dearmor -o /usr/share/keyrings/r-project.gpg
24 | echo "deb [signed-by=/usr/share/keyrings/r-project.gpg] https://cloud.r-project.org/bin/linux/ubuntu ${LSB_RELEASE}-cran40/" > /etc/apt/sources.list.d/r-project.list
25 | apt-get update
26 |
27 | # Install R runtime.
28 | #
29 | apt-get --no-install-recommends -y install r-base-core
30 | check_exit_code "Success: Installed R runtime." "Error: Failed to install R runtime."
31 |
32 | DEFAULT_R_HOME=/usr/lib/R
33 |
34 | # Find R_HOME from user, or set to default for installing Rcpp and RInside.
35 | # Error code 1 is generic bash error.
36 | #
37 | if [ -z "${R_HOME}" ]; then
38 | if [ -d "${DEFAULT_R_HOME}" ]; then
39 | R_HOME=${DEFAULT_R_HOME}
40 | else
41 | echo "R_HOME is empty"
42 | exit 1
43 | fi
44 | fi
45 | R_LIBRARY_PATH=${R_HOME}/library
46 |
47 | # Remove codetools from default library so it doesn't interfere with Rcpp installation below.
48 | #
49 | ${R_HOME}/bin/R -e "remove.packages('codetools', lib = '${R_LIBRARY_PATH}')"
50 |
51 | # Install Rcpp.
52 | #
53 | ${R_HOME}/bin/R -e "install.packages('https://cran.r-project.org/src/contrib/Archive/Rcpp/Rcpp_1.0.13.tar.gz', lib = '${R_LIBRARY_PATH}', repos = NULL, type='source')"
54 | ${R_HOME}/bin/R -e "stopifnot(require(Rcpp))"
55 | check_exit_code "Success: Installed Rcpp package." "Error: Failed to install Rcpp package."
56 |
57 | # Install RInside.
58 | #
59 | ${R_HOME}/bin/R -e "install.packages('https://cran.r-project.org/src/contrib/Archive/RInside/RInside_0.2.15.tar.gz', lib = '${R_LIBRARY_PATH}', repos = NULL, , type='source')"
60 | ${R_HOME}/bin/R -e "stopifnot(require(RInside))"
61 | check_exit_code "Success: Installed RInside package." "Error: Failed to install RInside package."
62 |
63 | exit $?
64 |
--------------------------------------------------------------------------------
/language-extensions/R/src/RColumn.cpp:
--------------------------------------------------------------------------------
1 | //**************************************************************************************************
2 | // RExtension : A language extension implementing the SQL Server
3 | // external language communication protocol for R.
4 | // Copyright (C) 2020 Microsoft Corporation.
5 | //
6 | // This file is part of RExtension.
7 | //
8 | // RExtension is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // RExtension is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with RExtension. If not, see .
20 | //
21 | // @File: RColumn.cpp
22 | //
23 | // Purpose:
24 | // Class encapsulating a DataSet's column attributes
25 | //
26 | //**************************************************************************************************
27 |
28 | #include "Common.h"
29 | #include "RColumn.h"
30 |
31 | using namespace std;
32 |
33 | //--------------------------------------------------------------------------------------------------
34 | // Name: RColumn::RColumn
35 | //
36 | // Description:
37 | // The constructor assigning the given column information to members.
38 | //
39 | RColumn::RColumn(
40 | const SQLCHAR *columnName,
41 | SQLSMALLINT columnNameLength,
42 | SQLSMALLINT dataType,
43 | SQLULEN columnSize,
44 | SQLSMALLINT decimalDigits,
45 | SQLSMALLINT nullable)
46 | {
47 | const char *name = static_cast(
48 | static_cast(columnName));
49 |
50 | // columnNameLength does not include the null terminator.
51 | //
52 | #if defined(_DEBUG)
53 | if (static_cast(columnNameLength) != strlen(name))
54 | {
55 | throw invalid_argument("Invalid column name length, it doesn't match string length.");
56 | }
57 | #endif
58 |
59 | // Store the information for this column
60 | //
61 | m_name = string(name, columnNameLength);
62 | m_dataType = dataType;
63 | m_size = columnSize;
64 | m_decimalDigits = decimalDigits;
65 | m_nullable = nullable;
66 | }
67 |
--------------------------------------------------------------------------------
/language-extensions/java/include/JniHelper.h:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: JniHelper.h
6 | //
7 | // Purpose:
8 | // Wrappers around commonly used JNI functions
9 | //
10 | //*********************************************************************
11 | #pragma once
12 |
13 | #include "Common.h"
14 | #include
15 |
16 | //---------------------------------------------------------------------
17 | // Description:
18 | // Wrapper class around commonly used JNI functions
19 | //
20 | class JniHelper
21 | {
22 | public:
23 | // Checks if an Java exception occurred and throws an exception
24 | //
25 | static void ThrowOnJavaException(JNIEnv *env);
26 |
27 | // Checks if an Java exception occurred and throws an exception
28 | //
29 | static void ThrowOnJavaException(JNIEnv *env, std::string &&errorMsg);
30 |
31 | // Logs the Java exception
32 | //
33 | static void LogJavaException(JNIEnv *env);
34 |
35 | // Finds the method ID for the class, name, and signature
36 | //
37 | static jmethodID FindMethod(
38 | JNIEnv *env,
39 | jclass jClass,
40 | const std::string &funcName,
41 | const std::string &funcSignature);
42 | };
43 |
44 | //---------------------------------------------------------------------
45 | // Description:
46 | // In JNI, local references are associated with the current local frame,
47 | // when call native code from Java these are created and managed automatically.
48 | // But when calling Java from native, there is no local frame created by default.
49 | // This class manages a local frame pushing and popping, when this object is
50 | // destroyed all the JNI local references created during the lifetime of this
51 | // object are released.
52 | //
53 | class AutoJniLocalFrame
54 | {
55 | public:
56 | AutoJniLocalFrame(JNIEnv *env, jint capacity)
57 | {
58 | assert(env != nullptr);
59 |
60 | m_env = env;
61 |
62 | m_env->PushLocalFrame(capacity);
63 | }
64 |
65 | ~AutoJniLocalFrame()
66 | {
67 | m_env->PopLocalFrame(nullptr);
68 | }
69 |
70 | private:
71 | JNIEnv *m_env;
72 | };
73 |
74 | //---------------------------------------------------------------------
75 | // Description:
76 | // Specific runtime exception indicating a Java exception has occurred
77 | //
78 | class java_exception_error : public std::runtime_error
79 | {
80 | using runtime_error::runtime_error;
81 | };
82 |
--------------------------------------------------------------------------------
/test/googletest/build/windows/build-googletest.cmd:
--------------------------------------------------------------------------------
1 | @ECHO off
2 | SETLOCAL
3 |
4 | SET ENL_ROOT=%~dp0..\..\..\..
5 | SET PACKAGES_ROOT=%ENL_ROOT%\packages
6 | SET CMAKE_ROOT=%PACKAGES_ROOT%\CMake-win64.3.15.5
7 | SET GTEST_HOME=%ENL_ROOT%\test\googletest
8 | SET BUILD_OUTPUT=%ENL_ROOT%\build-output\googletest\windows
9 |
10 | REM Call the root level restore-packages
11 | REM
12 | CALL %ENL_ROOT%\restore-packages.cmd
13 |
14 | REM Get RTools35 for mingw32-make and rtools40 for g++ v8.3.0 that works with C++17.
15 | REM
16 | SET RTOOLS_HOME=%PACKAGES_ROOT%\Rtools
17 | IF NOT EXIST %RTOOLS_HOME% (
18 | MKDIR %RTOOLS_HOME%
19 | powershell -Command "Invoke-WebRequest https://cran.r-project.org/bin/windows/Rtools/Rtools35.exe -OutFile %RTOOLS_HOME%\Rtools35.exe"
20 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to download Rtools3.5." || EXIT /b %ERRORLEVEL%
21 | powershell -Command "Invoke-WebRequest https://cran.r-project.org/bin/windows/Rtools/rtools40-x86_64.exe -OutFile %RTOOLS_HOME%\rtools40.exe"
22 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to download Rtools4.0." || EXIT /b %ERRORLEVEL%
23 | REM Install RTools
24 | REM
25 | %RTOOLS_HOME%\Rtools35.exe /VERYSILENT /DIR="C:\Rtools\"
26 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to install Rtools3.5." || EXIT /b %ERRORLEVEL%
27 | %RTOOLS_HOME%\rtools40.exe /VERYSILENT /DIR="C:\rtools40\"
28 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to install Rtools4.0." || EXIT /b %ERRORLEVEL%
29 | )
30 |
31 | RMDIR /s /q %BUILD_OUTPUT%
32 | MKDIR %BUILD_OUTPUT%
33 | PUSHD %BUILD_OUTPUT%
34 |
35 | REM Make sure g++, mingw32-make and R.dll are in the PATH.
36 | REM Do not enclose the C:\Rtools\mingw_64\bin path in quotes - cmake test fails
37 | REM
38 | SET PATH=C:\rtools40\mingw64\bin;C:\Rtools\mingw_64\bin;%R_HOME%\bin\x64;%PATH%
39 |
40 | CALL "%CMAKE_ROOT%\bin\cmake.exe" ^
41 | -G "MinGW Makefiles" ^
42 | -DCMAKE_MAKE_PROGRAM=mingw32-make ^
43 | -DCMAKE_INSTALL_PREFIX:PATH=%BUILD_OUTPUT% ^
44 | -DPLATFORM=windows ^
45 | %GTEST_HOME%\src
46 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to configure googletest-framework || EXIT /b %ERRORLEVEL%
47 |
48 | REM Call build
49 | REM
50 | CALL "mingw32-make.exe" all
51 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to build googletest-framework." || EXIT /b %ERRORLEVEL%
52 |
53 | REM Continue building using more configs until argv has been exhausted
54 | REM
55 | IF NOT "%~1"=="" GOTO LOOP
56 |
57 | EXIT /b %ERRORLEVEL%
58 |
59 | :CHECKERROR
60 | IF %1 NEQ 0 (
61 | ECHO %2
62 | EXIT /b %1
63 | )
64 |
65 | EXIT /b 0
66 |
--------------------------------------------------------------------------------
/language-extensions/R/include/RColumn.h:
--------------------------------------------------------------------------------
1 | //**************************************************************************************************
2 | // RExtension : A language extension implementing the SQL Server
3 | // external language communication protocol for R.
4 | // Copyright (C) 2020 Microsoft Corporation.
5 | //
6 | // This file is part of RExtension.
7 | //
8 | // RExtension is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // RExtension is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with RExtension. If not, see .
20 | //
21 | // @File: RColumn.h
22 | //
23 | // Purpose:
24 | // Class encapsulating a dataset's column attributes.
25 | //
26 | //**************************************************************************************************
27 |
28 | #pragma once
29 |
30 | //--------------------------------------------------------------------------------------------------
31 | // Name: RColumn
32 | //
33 | // Description:
34 | // Class encapsulating a dataset's column attributes.
35 | //
36 | class RColumn
37 | {
38 | public:
39 |
40 | RColumn(
41 | const SQLCHAR *columnName,
42 | SQLSMALLINT columnNameLength,
43 | SQLSMALLINT dataType,
44 | SQLULEN columnSize,
45 | SQLSMALLINT decimalDigits,
46 | SQLSMALLINT nullable);
47 |
48 | const std::string& Name() const
49 | {
50 | return m_name;
51 | }
52 |
53 | SQLSMALLINT DataType() const
54 | {
55 | return m_dataType;
56 | }
57 |
58 | SQLULEN Size() const
59 | {
60 | return m_size;
61 | }
62 |
63 | SQLSMALLINT Nullable() const
64 | {
65 | return m_nullable;
66 | }
67 |
68 | SQLSMALLINT DecimalDigits() const
69 | {
70 | return m_decimalDigits;
71 | }
72 |
73 | private:
74 |
75 | // Name of the column.
76 | //
77 | std::string m_name;
78 |
79 | // Data Type of the column.
80 | //
81 | SQLSMALLINT m_dataType;
82 |
83 | // Size of the column.
84 | //
85 | SQLULEN m_size;
86 |
87 | // The column is nullable or not.
88 | //
89 | SQLSMALLINT m_nullable;
90 |
91 | // Decimal digits of the column.
92 | //
93 | SQLSMALLINT m_decimalDigits;
94 | };
95 |
--------------------------------------------------------------------------------
/language-extensions/java/include/JavaExtensionUtils.h:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: JavaExtensionUtils.h
6 | //
7 | // Purpose:
8 | // Utility functions used by the Java extension.
9 | //
10 | //*********************************************************************
11 | #pragma once
12 |
13 | #include "Common.h"
14 |
15 | //---------------------------------------------------------------------
16 | // Description:
17 | // General utility functions for the Java extension
18 | //
19 | class JavaExtensionUtils
20 | {
21 | public:
22 | // Get the value of an enviroment variable
23 | //
24 | static std::string GetEnvVariable(const std::string &name);
25 |
26 | // Get the platform specifc classpath seperator
27 | //
28 | static const char GetClassPathSeparator();
29 |
30 | // Get the platform specifc path seperator
31 | //
32 | static const char GetPathSeparator();
33 |
34 | // Combines two paths
35 | //
36 | static std::string CombinePath(const std::string &basePath, const std::string &pathToAdd);
37 |
38 | // Determines if the file path is valid
39 | //
40 | static bool IsValidFile(const std::string &file);
41 |
42 | // Split a string based on a delimiter
43 | //
44 | static std::vector SplitString(const std::string &str, const char delimiter);
45 |
46 | // Creates a JVM
47 | //
48 | static JNIEnv* CreateJvm();
49 |
50 | // Cleans up JVM
51 | //
52 | static void CleanupJvm();
53 |
54 | private:
55 | // Function pointer definition for JNI_CreateJVM
56 | //
57 | using fn_createJvm = jint(*)(JavaVM **pvm, void **penv, void *args);
58 |
59 | // Constructs the classpath from the enviroment variable,
60 | // and external library paths
61 | //
62 | static std::string GetClassPath();
63 |
64 | // Constructs the path to the JVM library to load
65 | //
66 | static std::string GetJvmPath();
67 |
68 | // Constructs the platform specific relative path to the JVM with respect to
69 | // the JRE_HOME path
70 | //
71 | static const std::string& GetRelativeJvmPath();
72 |
73 | // Returns the platform specific name of the JVM library
74 | //
75 | static const std::string& GetJvmFilename();
76 |
77 | // Loads the JVM library and returns a function pointer to the JNICreate_JVM
78 | //
79 | static fn_createJvm LoadJvm(const std::string &jvmPath);
80 |
81 | // Cleans up the JVM instance
82 | //
83 | static void ShutdownJvm(JavaVM *jvm);
84 |
85 | // Unloads the JVM library
86 | //
87 | static void UnloadJvm();
88 | };
89 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Microsoft SQL Server Language Extensions
3 |
4 | Welcome to the SQL Server Language Extensions project!
5 |
6 | Starting in SQL Server 2019, we have added support for language extensibility, which means that you can now execute code in various languages like R, Python and Java from SQL Server.
7 |
8 | To download the released prebuilt versions of these extensions, go to the [Releases section of this repository](https://github.com/microsoft/sql-server-language-extensions/releases). Download the latest version of whichever extension corresponds to your machine configuration (Windows or Linux). There are separate releases for each language extension.
9 |
10 | We hope you enjoy using Microsoft SQL Server and the language extension feature.
11 |
12 | -SQL Server Team
13 |
14 | ## Documentation
15 |
16 | You can read more about how to use language extensions and how to use Java in SQL Server 2019 in the Microsoft [documentation](https://docs.microsoft.com/en-us/sql/language-extensions/language-extensions-overview?view=sqlallproducts-allversions).
17 |
18 | Tutorials and documentation for the R and Python extensions can be found here:
19 |
20 | [Python Documentation](https://docs.microsoft.com/en-us/sql/machine-learning/install/custom-runtime-python?view=sql-server-ver15)
21 |
22 | [R Documentation](https://docs.microsoft.com/en-us/sql/machine-learning/install/custom-runtime-r?view=sql-server-ver15)
23 |
24 | ## Custom Builds
25 |
26 | To build your own version of the language extensions, refer to each respective language's README file. \
27 | For example, to modify and build a custom version of the R Extension, go to [language-extensions/R/README.md](language-extensions/R/README.md).
28 |
29 | ## Contributing
30 |
31 | This project welcomes contributions and suggestions. Most contributions require you to agree to a
32 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
33 | the rights to use your contribution. For details, visit https://cla.microsoft.com.
34 |
35 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
36 | a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
37 | provided by the bot. You will only need to do this once across all repos using our CLA.
38 |
39 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
40 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
41 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
42 |
--------------------------------------------------------------------------------
/language-extensions/R/test/build/linux/build-RExtension-test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | function check_exit_code {
4 | EXIT_CODE=$?
5 | if [ ${EXIT_CODE} -eq 0 ]; then
6 | echo $1
7 | else
8 | echo $2
9 | exit ${EXIT_CODE}
10 | fi
11 | }
12 |
13 | function build {
14 | # Set cmake config to first arg
15 | #
16 | CMAKE_CONFIGURATION=$1
17 | if [ -z "${CMAKE_CONFIGURATION}" ]; then
18 | CMAKE_CONFIGURATION=release
19 | fi
20 |
21 | rm -rf ${REXTENSIONTEST_WORKING_DIR}/${CMAKE_CONFIGURATION}
22 | mkdir -p ${REXTENSIONTEST_WORKING_DIR}/${CMAKE_CONFIGURATION}
23 |
24 | pushd ${REXTENSIONTEST_WORKING_DIR}
25 |
26 | # Compile
27 | #
28 | cmake -DCMAKE_INSTALL_PREFIX:PATH=${REXTENSIONTEST_WORKING_DIR}/${CMAKE_CONFIGURATION} \
29 | -DCMAKE_BUILD_TYPE=${CMAKE_CONFIGURATION} \
30 | -DENL_ROOT=${ENL_ROOT} \
31 | -DPLATFORM=linux \
32 | -DR_HOME=${R_HOME} \
33 | -DR_INCLUDE_DIR=${R_INCLUDE} \
34 | ${REXTENSIONTEST_SRC_DIR}
35 | cmake --build ${REXTENSIONTEST_WORKING_DIR} --target install
36 |
37 | # Check the exit code of the compiler and exit appropriately so that build will fail.
38 | #
39 | check_exit_code "Success: Built RExtension-test" "Error: Failed to build RExtension-test"
40 |
41 | # Move the generated libs to configuration folder
42 | mv RExtension-test ${CMAKE_CONFIGURATION}/
43 |
44 | popd
45 | }
46 |
47 | # Enlistment root and location of RExtension-test
48 | #
49 | SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
50 | ENL_ROOT=${SCRIPTDIR}/../../../../..
51 | REXTENSIONTEST_HOME=${ENL_ROOT}/language-extensions/R/test/
52 |
53 | # Set environment variables required in Cmake
54 | #
55 | PACKAGES_ROOT=${ENL_ROOT}/packages
56 | REXTENSIONTEST_SRC_DIR=${REXTENSIONTEST_HOME}/src
57 | REXTENSIONTEST_WORKING_DIR=${ENL_ROOT}/build-output/RExtension-test/linux
58 |
59 | DEFAULT_R_HOME=/usr/lib/R
60 | DEFAULT_R_INCLUDE=/usr/share/R/include
61 |
62 | # Find R_HOME from user, or set to default for testing.
63 | # Error code 1 is generic bash error.
64 | #
65 | if [ -z "${R_HOME}" ]; then
66 | if [ -d "${DEFAULT_R_HOME}" ]; then
67 | export R_HOME=${DEFAULT_R_HOME}
68 | else
69 | echo "R_HOME is empty"
70 | exit 1
71 | fi
72 | fi
73 |
74 | # Find R_INCLUDE from user, or set to default for building the test.
75 | # Error code 1 is generic bash error.
76 | #
77 | if [ -z "${R_INCLUDE}" ]; then
78 | if [ -d "${DEFAULT_R_INCLUDE}" ]; then
79 | export R_INCLUDE=${DEFAULT_R_INCLUDE}
80 | else
81 | echo "R_INCLUDE is empty"
82 | exit 1
83 | fi
84 | fi
85 |
86 | # Build in release mode if nothing is specified
87 | #
88 | if [ "$1" == "" ]; then
89 | set -- release
90 | fi
91 |
92 | while [ "$1" != "" ]; do
93 | # Advance arg passed to build.cmd
94 | #
95 | build $1
96 | shift
97 | done;
98 |
--------------------------------------------------------------------------------
/language-extensions/R/src/RPathSettings.cpp:
--------------------------------------------------------------------------------
1 | //**************************************************************************************************
2 | // RExtension : A language extension implementing the SQL Server
3 | // external language communication protocol for R.
4 | // Copyright (C) 2020 Microsoft Corporation.
5 | //
6 | // This file is part of RExtension.
7 | //
8 | // RExtension is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // RExtension is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with RExtension. If not, see .
20 | //
21 | // @File: RPathSettings.cpp
22 | //
23 | // Purpose:
24 | // Global class to keep language runtime path settings for both platforms.
25 | //
26 | //**************************************************************************************************
27 |
28 | #include "Common.h"
29 |
30 | using namespace std;
31 |
32 | string RPathSettings::sm_languagePath;
33 | string RPathSettings::sm_languageParams;
34 | string RPathSettings::sm_privateLibraryPath;
35 | string RPathSettings::sm_publicLibraryPath;
36 | string RPathSettings::sm_RHomePath;
37 |
38 | //--------------------------------------------------------------------------------------------------
39 | // Name: RPathSettings::Init
40 | //
41 | // Description:
42 | // Initialize the class
43 | //
44 | void RPathSettings::Init(
45 | const SQLCHAR *languageParams,
46 | const SQLCHAR *languagePath,
47 | const SQLCHAR *publicLibraryPath,
48 | const SQLCHAR *privateLibraryPath)
49 | {
50 | LOG("RPathSettings::Init");
51 |
52 | // nullptrs are mapped to empty strings - has the same effect when
53 | // the paths are used and avoids an additional flag.
54 | //
55 | sm_languageParams =
56 | (languageParams == nullptr) ? "" : static_cast(
57 | static_cast(languageParams));
58 |
59 | sm_languagePath =
60 | (languagePath == nullptr) ? "" : static_cast(
61 | static_cast(languagePath));
62 |
63 | sm_publicLibraryPath =
64 | (publicLibraryPath == nullptr) ? "" : static_cast(
65 | static_cast(publicLibraryPath));
66 |
67 | sm_privateLibraryPath =
68 | (privateLibraryPath == nullptr) ? "" : static_cast(
69 | static_cast(privateLibraryPath));
70 | }
71 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/sample/regex/pkg/RegexSample.cs:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: RegexSample.cs
6 | //
7 | // Purpose:
8 | // Regex sample class using a regular expression that checks if a text contains the word "C#" or "c#"
9 | //
10 | //*********************************************************************
11 | using System;
12 | using System.Runtime.InteropServices;
13 | using System.Collections.Generic;
14 | using Microsoft.Data.Analysis;
15 | using Microsoft.SqlServer.CSharpExtension.SDK;
16 | using System.Text.RegularExpressions;
17 |
18 | namespace UserExecutor
19 | {
20 | ///
21 | /// This class extends the AbstractSqlServerExtensionExecutor and uses
22 | /// a regular expression that checks if a text contains the word "C#" or "c#"
23 | ///
24 | public class CSharpRegexExecutor: AbstractSqlServerExtensionExecutor
25 | {
26 | ///
27 | /// This method overrides the Execute method from AbstractSqlServerExtensionExecutor.
28 | ///
29 | ///
30 | /// A C# DataFrame contains the input dataset.
31 | ///
32 | ///
33 | /// A Dictionary contains the parameters from SQL server with name as the key.
34 | ///
35 | ///
36 | /// A C# DataFrame contains the output dataset.
37 | ///
38 | public override DataFrame Execute(DataFrame input, Dictionary sqlParams){
39 | // Drop NULL values and sort by id
40 | //
41 | input = input.DropNulls().OrderBy("id");
42 |
43 | // Create empty output DataFrame with two columns
44 | //
45 | DataFrame output = new DataFrame(new PrimitiveDataFrameColumn("id", 0), new StringDataFrameColumn("text", 0));
46 |
47 | // Filter text containing specific substring using regex expression
48 | //
49 | DataFrameColumn texts = input.Columns["text"];
50 | for(int i = 0; i < texts.Length; ++i)
51 | {
52 | if(Regex.IsMatch((string)texts[i], sqlParams["@regexExpr"]))
53 | {
54 | output.Append(input.Rows[i], true);
55 | }
56 | }
57 |
58 | // Modify the parameters
59 | //
60 | sqlParams["@rowsCount"] = output.Rows.Count;
61 | sqlParams["@regexExpr"] = "Success!";
62 |
63 | // Return output dataset as a DataFrame
64 | //
65 | return output;
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/language-extensions/python/include/PythonLibrarySession.h:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // Copyright (C) Microsoft Corporation.
3 | // Distributed under the Boost Software License, Version 1.0.
4 | // (See accompanying file LICENSE_1_0.txt or copy at
5 | // https://www.boost.org/LICENSE_1_0.txt)
6 | //
7 | // @File: PythonLibrarySession.h
8 | //
9 | // Purpose:
10 | // Class encapsulating operations performed in a library management session
11 | //
12 | //*************************************************************************************************
13 |
14 | #pragma once
15 | #include "Common.h"
16 | #ifdef _WIN64
17 | #include
18 | #else
19 | #include
20 | #endif
21 |
22 | class PythonLibrarySession
23 | {
24 | public:
25 |
26 | // Initializes the Python library session, initialize the main namespace.
27 | //
28 | void Init(const SQLGUID *sessionId);
29 |
30 | // Install the specified library.
31 | //
32 | SQLRETURN InstallLibrary(
33 | std::string tempFolder,
34 | SQLCHAR *libraryName,
35 | SQLINTEGER libraryNameLength,
36 | SQLCHAR *libraryFile,
37 | SQLINTEGER libraryFileLength,
38 | SQLCHAR *libraryInstallDirectory,
39 | SQLINTEGER libraryInstallDirectoryLength);
40 |
41 | // Uninstall the specified library.
42 | //
43 | SQLRETURN UninstallLibrary(
44 | SQLCHAR *libraryName,
45 | SQLINTEGER libraryNameLength,
46 | SQLCHAR *libraryInstallDirectory,
47 | SQLINTEGER libraryInstallDirectoryLength);
48 |
49 | #ifdef _WIN64
50 | // Get top level directory/ies for a package
51 | //
52 | std::vector GetTopLevel(
53 | std::string libName,
54 | std::string installDir);
55 |
56 | // Get all the artifacts we can find of a package that are in the path
57 | //
58 | std::vector GetAllArtifacts(
59 | std::string libName,
60 | std::string path);
61 | #else
62 | // Get top level directory/ies for a package
63 | //
64 | std::vector GetTopLevel(
65 | std::string libName,
66 | std::string installDir);
67 |
68 | // Get all the artifacts we can find of a package that are in the path
69 | //
70 | std::vector GetAllArtifacts(
71 | std::string libName,
72 | std::string path);
73 | #endif
74 |
75 | private:
76 | SQLGUID m_sessionId{ 0, 0, 0, {0} };
77 |
78 | // The underlying boost::python namespace, which contains all the python variables.
79 | // We execute any python scripts on this namespace.
80 | //
81 | boost::python::object m_mainNamespace;
82 | };
83 |
--------------------------------------------------------------------------------
/language-extensions/python/test/src/PythonInitTests.cpp:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // Copyright (C) Microsoft Corporation.
3 | // Distributed under the Boost Software License, Version 1.0.
4 | // (See accompanying file LICENSE_1_0.txt or copy at
5 | // https://www.boost.org/LICENSE_1_0.txt)
6 | //
7 | // @File: PythonInitTests.cpp
8 | //
9 | // Purpose:
10 | // Test the Python extension initialization and
11 | // session initialization using the Extension API
12 | //
13 | //*************************************************************************************************
14 | #include "PythonExtensionApiTests.h"
15 |
16 | using namespace std;
17 |
18 | namespace ExtensionApiTest
19 | {
20 | // Name: TestInitWithNulls
21 | //
22 | // Description:
23 | // Test Init() API with all nullptrs.
24 | // This tests the extension initialization, using nullptrs because
25 | // param and library paths are optional.
26 | //
27 | TEST_F(PythonExtensionApiTests, TestInitWithNulls)
28 | {
29 | SQLRETURN result = Init(
30 | nullptr, // Extension Params
31 | 0, // Extension Params Length
32 | nullptr, // Extension Path
33 | 0, // Extension Path Length
34 | nullptr, // Public Library Path
35 | 0, // Public Library Path Length
36 | nullptr, // Private Library Path
37 | 0 // Private Library Path Length
38 | );
39 |
40 | EXPECT_EQ(result, SQL_SUCCESS);
41 | }
42 |
43 | // Name: TestInitWithValues
44 | //
45 | // Description:
46 | // Test Init() API with actual values.
47 | //
48 | TEST_F(PythonExtensionApiTests, TestInitWithValues)
49 | {
50 | SQLCHAR *extensionParams = nullptr;
51 | SQLULEN extensionParamsLength = 0;
52 | string extensionPath = "C:/Path/To/ExternalLanguages/1/65554";
53 | SQLULEN extensionPathLength = extensionPath.length();
54 | string publicLibraryPath = "C:/Path/To/ExternalLanguages/1/65554/1";
55 | SQLULEN publicLibraryPathLength = publicLibraryPath.length();
56 | SQLCHAR *privateLibraryPath = nullptr;
57 | SQLULEN privateLibraryPathLength = 0;
58 |
59 | SQLCHAR *unsignedExtensionPath = static_cast(
60 | static_cast(const_cast(extensionPath.c_str())));
61 | SQLCHAR *unsignedPublicLibraryPath = static_cast(
62 | static_cast(const_cast(publicLibraryPath.c_str())));
63 |
64 | SQLRETURN result = Init(extensionParams,
65 | extensionParamsLength,
66 | unsignedExtensionPath,
67 | extensionPathLength,
68 | unsignedPublicLibraryPath,
69 | publicLibraryPathLength,
70 | privateLibraryPath,
71 | privateLibraryPathLength
72 | );
73 |
74 | EXPECT_EQ(result, SQL_SUCCESS);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/language-extensions/R/common/include/Unicode.h:
--------------------------------------------------------------------------------
1 | //**************************************************************************************************
2 | // RExtension : A language extension implementing the SQL Server
3 | // external language communication protocol for R.
4 | // Copyright (C) 2020 Microsoft Corporation.
5 | //
6 | // This file is part of RExtension.
7 | //
8 | // RExtension is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // RExtension is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with RExtension. If not, see .
20 | //
21 | // @File: Unicode.h
22 | //
23 | // Purpose:
24 | // Functions providing lengths and conversion between utf16, utf8 encoded unicode characters.
25 | //
26 | //**************************************************************************************************
27 | #pragma once
28 |
29 | #include
30 |
31 | namespace estd
32 | {
33 | std::u16string ToUtf16(const std::string &str);
34 | std::string ToUtf8(const std::u16string &str);
35 |
36 | std::u16string ToUtf16(const char *s, size_t len);
37 | std::string ToUtf8(const char16_t *s, size_t len);
38 |
39 | // These versions avoid memory allocation if the output string is big enough.
40 | // Useful for loops when multiple strings are converted.
41 | //
42 | void ToUtf16(const std::string &u8, std::u16string &u16);
43 | void ToUtf8(const std::u16string &str, std::string &u8);
44 | void ToUtf16(const char *s, size_t len, std::u16string &u16);
45 | void ToUtf8(const char16_t *s, size_t len, std::string &u8, bool throwOnError = false);
46 |
47 | // Returns the number of chars (bytes) in the string
48 | //
49 | size_t Utf8Size(const std::string &str);
50 |
51 | // Returns the number of chars (bytes) in the UTF8 representation of the string
52 | //
53 | size_t Utf8Size(const std::u16string &str);
54 | size_t Utf8Size(const char16_t *s, size_t l);
55 |
56 | // Returns the number of char16s in the string
57 | //
58 | size_t Utf16Size(const std::u16string &str);
59 |
60 | // Returns the number of char16s in the UTF16 representation of the string
61 | //
62 | size_t Utf16Size(const std::string &str);
63 | size_t Utf16Size(const char *s, size_t l);
64 |
65 | // Returns True if the string is a valid UTF8, false otherwise.
66 | //
67 | bool IsValidUTF8(const char* str, int strlen);
68 | }
69 |
--------------------------------------------------------------------------------
/language-extensions/R/src/linux/RPathSettings_linux.cpp:
--------------------------------------------------------------------------------
1 | //**************************************************************************************************
2 | // RExtension : A language extension implementing the SQL Server
3 | // external language communication protocol for R.
4 | // Copyright (C) 2020 Microsoft Corporation.
5 | //
6 | // This file is part of RExtension.
7 | //
8 | // RExtension is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // RExtension is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with RExtension. If not, see .
20 | //
21 | // @File: RPathSettings_linux.cpp
22 | //
23 | // Purpose:
24 | // Global class to keep language runtime path settings for linux.
25 | //
26 | //**************************************************************************************************
27 |
28 | #include "Common.h"
29 |
30 | using namespace std;
31 |
32 | //--------------------------------------------------------------------------------------------------
33 | // Name: RPathSettings::CheckAndSetRHome
34 | //
35 | // Description:
36 | // Checks if R_HOME is set, and sets it to be the language path if not already set.
37 | // Throws and exception if there is an error setting it.
38 | //
39 | void RPathSettings::CheckAndSetRHome()
40 | {
41 | LOG("RPathSettings::CheckAndSetRHome");
42 |
43 | sm_RHomePath =
44 | Utilities::GetEnvVariable(
45 | "R_HOME", // envVarName
46 | // No need to log error on linux if R_HOME is not defined, since we can set it below.
47 | //
48 | false); // logError
49 |
50 | if (sm_RHomePath == "")
51 | {
52 | int result = Utilities::SetEnvVariable("R_HOME", sm_languagePath);
53 | if (result != 0)
54 | {
55 | throw runtime_error("Error setting R_HOME");
56 | }
57 | else
58 | {
59 | sm_RHomePath = sm_languagePath;
60 | LOG("R_HOME set to be the extensionPath: " + sm_RHomePath);
61 | }
62 | }
63 | else
64 | {
65 | LOG("R_HOME is set as: " + sm_RHomePath);
66 | }
67 | }
68 |
69 | //--------------------------------------------------------------------------------------------------
70 | // Name: RPathSettings::CheckAndSetTZDir
71 | //
72 | // Description:
73 | // Its a no-op on linux since TZDIR is not useful on linux. The time zones are always looked up
74 | // from fixed path: /usr/share/zoneinfo
75 | //
76 | void RPathSettings::CheckAndSetTZDir()
77 | {
78 | }
79 |
--------------------------------------------------------------------------------
/language-extensions/R/include/Utilities.h:
--------------------------------------------------------------------------------
1 | //**************************************************************************************************
2 | // RExtension : A language extension implementing the SQL Server
3 | // external language communication protocol for R.
4 | // Copyright (C) 2020 Microsoft Corporation.
5 | //
6 | // This file is part of RExtension.
7 | //
8 | // RExtension is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // RExtension is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with RExtension. If not, see .
20 | //
21 | // @File: Utilities.h
22 | //
23 | // Purpose:
24 | // Utility functions
25 | //
26 | //**************************************************************************************************
27 |
28 | #pragma once
29 |
30 | class Utilities
31 | {
32 | public:
33 |
34 | // Converts a SQLGUID to a string
35 | //
36 | static std::string ConvertGuidToString(const SQLGUID * guid);
37 |
38 | // Splits the given character string using the delimiter and
39 | // adds the tokens to the input vector.
40 | //
41 | static void Tokenize(char *input, const char* delimiter, std::vector *tokens);
42 |
43 | // Given a constant string input, generates a unique pointer
44 | // pointing to a char array containing the same contents as that of the input
45 | //
46 | static std::unique_ptr GenerateUniquePtr(const std::string &input);
47 |
48 | // Gets the value of the given environment variable name.
49 | //
50 | static std::string GetEnvVariable(const std::string &envVarName, bool logError);
51 |
52 | // Sets the environment variable name to the specified value.
53 | //
54 | static int SetEnvVariable(const std::string &envVarName, const std::string &value);
55 |
56 | // From the given nanoSeconds value, generates a string
57 | // representing seconds after the decimal point.
58 | //
59 | static std::string GetSecondsAfterDecimalPointFromNanoSeconds(
60 | SQLUINTEGER nanoSeconds);
61 |
62 | // Finds the current time zone defined in R if any
63 | //
64 | static std::string GetTimeZoneInR();
65 |
66 | // Sets the time zone in R to the given value or unset it if the value is empty.
67 | //
68 | static void SetTimeZoneInR(std::string valueToSet);
69 |
70 | // Normalizes path strings by replacting \ with /
71 | //
72 | static std::string NormalizePathString(std::string pathString);
73 | };
74 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/language-extensions/R/test/include/Utilities.h:
--------------------------------------------------------------------------------
1 | //**************************************************************************************************
2 | // RExtension-test : Executable testing language extension that implements the SQL Server
3 | // external language communication protocol.
4 | // Copyright (C) 2020 Microsoft Corporation.
5 | //
6 | // This file is part of RExtension-test.
7 | //
8 | // RExtension-test is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // RExtension-test is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with RExtension-test. If not, see .
20 | //
21 | // @File: Utilities.cpp
22 | //
23 | // Purpose:
24 | // Utility functions
25 | //
26 | //**************************************************************************************************
27 |
28 | #pragma once
29 |
30 | # define LOCAL_DATE 1
31 | # define UTC_DATE 2
32 |
33 | class Utilities
34 | {
35 | public:
36 |
37 | // Gets the handle for the given library path after loading it dynamically
38 | //
39 | static void* CrossPlatLoadLibrary(
40 | const char *libPath);
41 |
42 | // Gets the function pointer for the given function name from the given library handle
43 | //
44 | static void* CrossPlatGetFunctionFromLibHandle(
45 | void *libHandle,
46 | const std::string &fnName);
47 |
48 | // Given a valid library handle, closes it.
49 | //
50 | static void CrossPlatCloseLibrary(
51 | void *libHandle);
52 |
53 | // Gets max length from given arrayOfLengths with size = rowsNumber.
54 | //
55 | static SQLINTEGER GetMaxLength(
56 | SQLINTEGER *arrayOfLengths,
57 | SQLULEN rowsNumber);
58 |
59 | // Gets the length of a wchar_t *.
60 | //
61 | static SQLULEN GetWStringLength(const wchar_t *wstr);
62 |
63 | // Returns the current system clock time in terms of time_t which represents number of seconds
64 | // since epoch January 1, 1970 00:00:00.
65 | //
66 | static time_t GetNow();
67 |
68 | // Gets the current date based on its type (UTC or local) in the form of a SQL_DATE_STRUCT.
69 | //
70 | template
71 | static SQL_DATE_STRUCT GetTodaysDate();
72 |
73 | // Convert the given SQLDateTimeType into an equivalent UTC SQLDateTimeType
74 | //
75 | template
76 | static SQLDateTimeType ToUtc(SQLDateTimeType givenTimeStamp);
77 |
78 | // Normalizes path string.
79 | //
80 | static std::string NormalizePathString(std::string pathString);
81 | };
82 |
--------------------------------------------------------------------------------
/language-extensions/python/build/linux/restore-packages.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
3 |
4 | export DEBIAN_FRONTEND=noninteractive
5 | apt-get update
6 | apt-get --no-install-recommends -y install curl zip unzip
7 |
8 | apt-get update
9 | apt-get install -y software-properties-common
10 | add-apt-repository -y ppa:deadsnakes/ppa
11 | apt-get update
12 |
13 | DEFAULT_PYTHONHOME=/usr
14 | BOOST_VERSION=1.87.0
15 | BOOST_VERSION_IN_UNDERSCORE=1_87_0
16 | PYTHON_VERSION=3.12
17 | NUMPY_VERSION=2.3.0
18 | PANDAS_VERSION=2.3.0
19 |
20 | apt-get install -y python3.12-dev python3.12 libpython3.12 libpython3.12-dev libboost-all-dev
21 | curl -sS https://bootstrap.pypa.io/get-pip.py | /usr/bin/python${PYTHON_VERSION}
22 |
23 | # Find PYTHONHOME from user, or set to default for tests.
24 | # Error code 1 is generic bash error.
25 | #
26 | if [ -z "${PYTHONHOME}" ]; then
27 | if [ -x "${DEFAULT_PYTHONHOME}" ]; then
28 | PYTHONHOME=${DEFAULT_PYTHONHOME}
29 | else
30 | echo "PYTHONHOME is empty"
31 | exit 1
32 | fi
33 | fi
34 |
35 | echo "Python home is ${PYTHONHOME}"
36 |
37 | # Lock versions of numpy and pandas to versions compatible for the defined python version
38 | #
39 | ${PYTHONHOME}/bin/python${PYTHON_VERSION} -m pip install --force-reinstall numpy==${NUMPY_VERSION}
40 | ${PYTHONHOME}/bin/python${PYTHON_VERSION} -m pip install --force-reinstall pandas==${PANDAS_VERSION}
41 |
42 | # Download and install boost, then navigate to boost root directory
43 | # Use /usr/local for boost installation to avoid conflicts with system packages
44 | #
45 | wget -O boost_${BOOST_VERSION_IN_UNDERSCORE}.tar.gz https://sourceforge.net/projects/boost/files/boost/${BOOST_VERSION}/boost_${BOOST_VERSION_IN_UNDERSCORE}.tar.gz/download
46 | tar xzvf boost_${BOOST_VERSION_IN_UNDERSCORE}.tar.gz -C /usr/local/lib/
47 | pushd /usr/local/lib/boost_${BOOST_VERSION_IN_UNDERSCORE}
48 |
49 | # Build defined python version of boost and boost python
50 | #
51 | ./bootstrap.sh --without-icu --with-python=${PYTHONHOME}/bin/python${PYTHON_VERSION} --with-python-version=${PYTHON_VERSION} --with-python-root=${PYTHONHOME}/lib/python${PYTHON_VERSION}
52 |
53 | echo "using python : ${PYTHON_VERSION} : ${PYTHONHOME}/bin/python${PYTHON_VERSION} : ${PYTHONHOME}/include/python${PYTHON_VERSION} : ${PYTHONHOME}/lib ;" >> project-config.jam
54 |
55 | # Change cxx flags to force boost to compile with -fPIC compilation, otherwise will fail linking when building libPythonExtension.so
56 | #
57 | sed -i 's/using gcc[^;]*;/using gcc : foo : g++ : -fPIC ;/g' project-config.jam
58 |
59 | ./b2 --clean
60 | # Build both debug and release variants, and both static and shared libraries
61 | ./b2 toolset=gcc variant=debug,release address-model=64 include=${PYTHONHOME}/include/python${PYTHON_VERSION}/ link=shared,static threading=multi -j12
62 |
63 | cp -rf boost /usr/local/include/
64 |
65 | popd
66 |
67 | exit $?
68 |
--------------------------------------------------------------------------------
/language-extensions/python/src/Logger.cpp:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // Copyright (C) Microsoft Corporation.
3 | // Distributed under the Boost Software License, Version 1.0.
4 | // (See accompanying file LICENSE_1_0.txt or copy at
5 | // https://www.boost.org/LICENSE_1_0.txt)
6 | //
7 | // @File: Logger.cpp
8 | //
9 | // Purpose:
10 | // Logging functions for extension
11 | //
12 | //*************************************************************************************************
13 |
14 | #include "Logger.h"
15 |
16 | #define TIMESTAMP_LENGTH 35
17 | using namespace std;
18 |
19 | char Logger::sm_timestampBuffer[TIMESTAMP_LENGTH] = { 0 };
20 |
21 | //-------------------------------------------------------------------------------------------------
22 | // Name: LogError
23 | //
24 | // Description:
25 | // Log an error to stderr with format "TIMESTAMP Error: ".
26 | //
27 | void Logger::LogError(const string &errorMsg)
28 | {
29 | cerr << GetCurrentTimestamp() << "Error: " << errorMsg << endl;
30 | }
31 |
32 | //-------------------------------------------------------------------------------------------------
33 | // Name: LogException
34 | //
35 | // Description:
36 | // Log a c++ exception to stderr with format "TIMESTAMP Exception
37 | // occurred: ".
38 | //
39 | void Logger::LogException(const exception &e)
40 | {
41 | cerr << GetCurrentTimestamp() << "Exception occurred: " << e.what() << endl;
42 | }
43 |
44 | //-------------------------------------------------------------------------------------------------
45 | // Name: Log
46 | //
47 | // Description:
48 | // Log a message to stdout with format "TIMESTAMP ".
49 | //
50 | void Logger::Log(const string &msg)
51 | {
52 | #if defined(_DEBUG)
53 | cout << GetCurrentTimestamp() << msg << endl;
54 | #endif
55 | }
56 |
57 | //-------------------------------------------------------------------------------------------------
58 | // Name: GetCurrentTimestamp
59 | //
60 | // Description:
61 | // Gets the current system time and format it to the SQL log format
62 | // (Year-Month-Day Hour:Minute:Second.Millisecond).
63 | //
64 | const std::string Logger::GetCurrentTimestamp()
65 | {
66 | #if defined ( _MSC_VER )
67 | SYSTEMTIME sysTime;
68 |
69 | GetLocalTime(&sysTime);
70 |
71 | sprintf_s(sm_timestampBuffer, TIMESTAMP_LENGTH,
72 | "%04d-%02d-%02d %02d:%02d:%02d.%02d\t",
73 | sysTime.wYear,
74 | sysTime.wMonth,
75 | sysTime.wDay,
76 | sysTime.wHour,
77 | sysTime.wMinute,
78 | sysTime.wSecond,
79 | sysTime.wMilliseconds / 10);
80 |
81 | return sm_timestampBuffer;
82 | #else
83 | time_t now = time(0);
84 | struct tm tstruct;
85 | char buf[80];
86 |
87 | tstruct = *localtime(&now);
88 | strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S.000\t", &tstruct); // No millisecond support
89 | return buf;
90 | #endif
91 | }
92 |
--------------------------------------------------------------------------------
/language-extensions/R/src/linux/Utilities_linux.cpp:
--------------------------------------------------------------------------------
1 | //**************************************************************************************************
2 | // RExtension : A language extension implementing the SQL Server
3 | // external language communication protocol for R.
4 | // Copyright (C) 2020 Microsoft Corporation.
5 | //
6 | // This file is part of RExtension.
7 | //
8 | // RExtension is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // RExtension is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with RExtension. If not, see .
20 | //
21 | // @File: Utilities_linux.cpp
22 | //
23 | // Purpose:
24 | // Utility functions implemented for the linux platform.
25 | //
26 | //**************************************************************************************************
27 |
28 | #include "Common.h"
29 |
30 | using namespace std;
31 |
32 | //--------------------------------------------------------------------------------------------------
33 | // Name: Utilities::GetEnvVariable
34 | //
35 | // Description:
36 | // Gets the value of the given environment variable name and if logError is true, logs an error
37 | // message if the variable is not found.
38 | //
39 | // Returns:
40 | // String value of the environment variable requested.
41 | //
42 | string Utilities::GetEnvVariable(const string &envVarName, bool logError)
43 | {
44 | string envVarValueString;
45 | char * envVarValue = getenv(envVarName.c_str());
46 | if (envVarValue != nullptr)
47 | {
48 | envVarValueString = string(const_cast(envVarValue),
49 | strlen(envVarValue));
50 | }
51 | else if (logError)
52 | {
53 | LOG_ERROR("Did not find the environment variable " + envVarName);
54 | }
55 |
56 | return envVarValueString;
57 | }
58 |
59 | //--------------------------------------------------------------------------------------------------
60 | // Name: Utilities::SetEnvVariable
61 | //
62 | // Description:
63 | // Sets the environment variable name to the specified value
64 | //
65 | // Returns:
66 | // Returns the result of the putenv operation. 0 indicates success, nonzero indicates error.
67 | //
68 | int Utilities::SetEnvVariable(const string &envVarName, const string &value)
69 | {
70 | errno = 0;
71 | string keyValue = string(envVarName + "=" + value);
72 | int result = putenv(const_cast(keyValue.c_str()));
73 | if (result != 0)
74 | {
75 | LOG_ERROR("Failed to set the value " + value +
76 | " to the environment variable " + envVarName +
77 | " with system error #" + to_string(errno) + ".");
78 | }
79 |
80 | return result;
81 | }
82 |
--------------------------------------------------------------------------------
/language-extensions/R/include/RPathSettings.h:
--------------------------------------------------------------------------------
1 | //**************************************************************************************************
2 | // RExtension : A language extension implementing the SQL Server
3 | // external language communication protocol for R.
4 | // Copyright (C) 2020 Microsoft Corporation.
5 | //
6 | // This file is part of RExtension.
7 | //
8 | // RExtension is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // RExtension is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with RExtension. If not, see .
20 | //
21 | // @File: RPathSettings.h
22 | //
23 | // Purpose:
24 | // Global class to keep language runtime path settings.
25 | //
26 | //**************************************************************************************************
27 |
28 | #pragma once
29 |
30 | //--------------------------------------------------------------------------------------------------
31 | // Name: RPathSettings
32 | //
33 | // Description:
34 | // Global class storing the language runtime paths and parameters.
35 | //
36 | class RPathSettings
37 | {
38 | public:
39 |
40 | // Initializes this global class
41 | //
42 | static void Init(
43 | const SQLCHAR *languageParams,
44 | const SQLCHAR *languagePath,
45 | const SQLCHAR *publicLibraryPath,
46 | const SQLCHAR *privateLibraryPath);
47 |
48 | // Gets the private library path sent by SQL Server
49 | //
50 | static const std::string& PrivateLibraryPath() {return sm_privateLibraryPath; }
51 |
52 | // Gets the public library path sent by SQL Server
53 | //
54 | static const std::string& PublicLibraryPath() {return sm_publicLibraryPath; }
55 |
56 | // Gets the extension root folder
57 | //
58 | static const std::string& RootPath() {return sm_languagePath; }
59 |
60 | // Gets the language parameters sent by SQL Server
61 | //
62 | static const std::string& Params() {return sm_languageParams; }
63 |
64 | // Checks if R_HOME is set, and sets it to be the language path if not already set.
65 | //
66 | static void CheckAndSetRHome();
67 |
68 | // Sets the environment variable TZDIR.
69 | //
70 | static void CheckAndSetTZDir();
71 |
72 | private:
73 |
74 | // Directory where R language extension library is extracted onto.
75 | //
76 | static std::string sm_languagePath;
77 |
78 | // Parameters passed to R language extension
79 | //
80 | static std::string sm_languageParams;
81 |
82 | // Private library path
83 | //
84 | static std::string sm_privateLibraryPath;
85 |
86 | // Public library path
87 | //
88 | static std::string sm_publicLibraryPath;
89 |
90 | // R_HOME path
91 | //
92 | static std::string sm_RHomePath;
93 | };
94 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/include/hostfxr.h:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 |
4 | #ifndef __HOSTFXR_H__
5 | #define __HOSTFXR_H__
6 |
7 | #include
8 | #include
9 |
10 | #if defined(_WIN32)
11 | #define HOSTFXR_CALLTYPE __cdecl
12 | #ifdef _WCHAR_T_DEFINED
13 | typedef wchar_t char_t;
14 | #else
15 | typedef unsigned short char_t;
16 | #endif
17 | #else
18 | #define HOSTFXR_CALLTYPE
19 | typedef char char_t;
20 | #endif
21 |
22 | enum hostfxr_delegate_type
23 | {
24 | hdt_com_activation,
25 | hdt_load_in_memory_assembly,
26 | hdt_winrt_activation,
27 | hdt_com_register,
28 | hdt_com_unregister,
29 | hdt_load_assembly_and_get_function_pointer
30 | };
31 |
32 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_main_fn)(const int argc, const char_t **argv);
33 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_main_startupinfo_fn)(
34 | const int argc,
35 | const char_t **argv,
36 | const char_t *host_path,
37 | const char_t *dotnet_root,
38 | const char_t *app_path);
39 |
40 | typedef void(HOSTFXR_CALLTYPE *hostfxr_error_writer_fn)(const char_t *message);
41 | typedef hostfxr_error_writer_fn(HOSTFXR_CALLTYPE *hostfxr_set_error_writer_fn)(hostfxr_error_writer_fn error_writer);
42 |
43 | typedef void* hostfxr_handle;
44 | typedef struct hostfxr_initialize_parameters
45 | {
46 | size_t size;
47 | const char_t *host_path;
48 | const char_t *dotnet_root;
49 | } hostfxr_initialize_parameters;
50 |
51 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_initialize_for_dotnet_command_line_fn)(
52 | int argc,
53 | const char_t **argv,
54 | const hostfxr_initialize_parameters *parameters,
55 | /*out*/ hostfxr_handle *host_context_handle);
56 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_initialize_for_runtime_config_fn)(
57 | const char_t *runtime_config_path,
58 | const hostfxr_initialize_parameters*parameters,
59 | /*out*/ hostfxr_handle *host_context_handle);
60 |
61 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_get_runtime_property_value_fn)(
62 | const hostfxr_handle host_context_handle,
63 | const char_t *name,
64 | /*out*/ const char_t **value);
65 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_set_runtime_property_value_fn)(
66 | const hostfxr_handle host_context_handle,
67 | const char_t *name,
68 | const char_t *value);
69 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_get_runtime_properties_fn)(
70 | const hostfxr_handle host_context_handle,
71 | /*inout*/ size_t * count,
72 | /*out*/ const char_t **keys,
73 | /*out*/ const char_t **values);
74 |
75 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_run_app_fn)(const hostfxr_handle host_context_handle);
76 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_get_runtime_delegate_fn)(
77 | const hostfxr_handle host_context_handle,
78 | enum hostfxr_delegate_type type,
79 | /*out*/ void **delegate);
80 |
81 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_close_fn)(const hostfxr_handle host_context_handle);
82 |
83 | #endif //__HOSTFXR_H__
84 |
--------------------------------------------------------------------------------
/language-extensions/python/src/PythonNamespace.cpp:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // Copyright (C) Microsoft Corporation.
3 | // Distributed under the Boost Software License, Version 1.0.
4 | // (See accompanying file LICENSE_1_0.txt or copy at
5 | // https://www.boost.org/LICENSE_1_0.txt)
6 | //
7 | // @File: PythonNamespace.cpp
8 | //
9 | // Purpose:
10 | // Global class to keep the global python namespace
11 | //
12 | //*************************************************************************************************
13 |
14 | #include "PythonNamespace.h"
15 | #include "PythonPathSettings.h"
16 |
17 | using namespace std;
18 | namespace bp = boost::python;
19 |
20 | //-------------------------------------------------------------------------------------------------
21 | // Name: PythonNamespace::Init
22 | //
23 | // Description:
24 | // Initialize the class
25 | //
26 | void PythonNamespace::Init()
27 | {
28 | sm_mainModule = bp::import("__main__");
29 | sm_mainNamespace = sm_mainModule.attr("__dict__");
30 |
31 | // Check that the module and namespace are populated, not None objects
32 | //
33 | if (sm_mainModule == bp::object() ||
34 | sm_mainNamespace == bp::object())
35 | {
36 | throw runtime_error("Main module or namespace was None");
37 | }
38 |
39 | // Setup the devnull device (which we do not have access to in Windows)
40 | // to redirect to a file. We create that file here for future use.
41 | // Also, import packages that we will need in later functions.
42 | //
43 | string setupScript =
44 | "import os\n"
45 | "import sys\n"
46 | "import platform\n"
47 | "from pandas import DataFrame\n"
48 | "import numpy as np\n"
49 | "_originalpath = list(sys.path)\n"
50 | "if platform.system() == 'Windows':\n"
51 | " oldnulldevice = os.devnull\n"
52 | " os.devnull = 'nulldeviceout.txt'\n"
53 | " nulhandle = open(os.devnull, 'w+')\n"
54 | " nulhandle.close()";
55 |
56 | bp::exec(setupScript.c_str(), sm_mainNamespace);
57 |
58 | string privateLibPath = PythonPathSettings::PrivateLibraryPath();
59 | string publicLibPath = PythonPathSettings::PublicLibraryPath();
60 |
61 | // Setup the path to include private and public external library paths
62 | // so that we can find the external packages that are installed.
63 | // We set the private/public paths in front of the sys.path so they are searched first.
64 | //
65 | sm_originalPath = bp::extract(bp::eval("sys.path", sm_mainNamespace));
66 | bp::list newPath(sm_originalPath);
67 | newPath.insert(0, bp::str(publicLibPath));
68 | newPath.insert(0, bp::str(privateLibPath));
69 |
70 | PySys_SetObject("path", newPath.ptr());
71 | }
72 |
73 | //-------------------------------------------------------------------------------------------------
74 | // Name: PythonNamespace::Cleanup
75 | //
76 | // Description:
77 | // Cleanup, reset the Python syspath
78 | //
79 | void PythonNamespace::Cleanup()
80 | {
81 | PySys_SetObject("path", sm_originalPath.ptr());
82 | }
83 |
84 | bp::object PythonNamespace::sm_mainNamespace;
85 | bp::object PythonNamespace::sm_mainModule;
86 | bp::object PythonNamespace::sm_originalPath;
87 |
--------------------------------------------------------------------------------
/language-extensions/R/src/windows/RPathSettings_win.cpp:
--------------------------------------------------------------------------------
1 | //**************************************************************************************************
2 | // RExtension : A language extension implementing the SQL Server
3 | // external language communication protocol for R.
4 | // Copyright (C) 2020 Microsoft Corporation.
5 | //
6 | // This file is part of RExtension.
7 | //
8 | // RExtension is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // RExtension is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with RExtension. If not, see .
20 | //
21 | // @File: RPathSettings_win.cpp
22 | //
23 | // Purpose:
24 | // Global class to keep language runtime path settings for windows.
25 | //
26 | //**************************************************************************************************
27 |
28 | #include "Common.h"
29 |
30 | using namespace std;
31 |
32 | //--------------------------------------------------------------------------------------------------
33 | // Name: RPathSettings::CheckAndSetRHome
34 | //
35 | // Description:
36 | // Checks if R_HOME is set and throws an exception if its not set.
37 | //
38 | void RPathSettings::CheckAndSetRHome()
39 | {
40 | LOG("RPathSettings::CheckAndSetRHome");
41 |
42 | sm_RHomePath =
43 | Utilities::GetEnvVariable(
44 | "R_HOME", // envVarName
45 | // We need to log error if R_HOME is not defined on Windows
46 | // since its too late to set it now.
47 | //
48 | true); // logError
49 |
50 | if (sm_RHomePath == "")
51 | {
52 | throw runtime_error("On Windows, R_HOME needs to be defined as"
53 | " a system environment variable.");
54 | }
55 | else
56 | {
57 | LOG("R_HOME is set as: " + sm_RHomePath);
58 | }
59 | }
60 |
61 | //--------------------------------------------------------------------------------------------------
62 | // Name: RPathSettings::SetTZDir
63 | //
64 | // Description:
65 | // Check if environment variable TZDIR is set.
66 | // If it is not set, set sm_RHomePath first and then set TZDIR to R_HOME\share\zoneinfo path
67 | // so that time zone information is available when calling OlsonNames() in R.
68 | //
69 | void RPathSettings::CheckAndSetTZDir()
70 | {
71 | LOG("RPathSettings::CheckAndSetTZDir");
72 |
73 | string tzDir =
74 | Utilities::GetEnvVariable(
75 | "TZDIR", // envVarName
76 | // No need to log error if TZDIR is not defined since we can set it below.
77 | //
78 | false); // logError
79 |
80 | if (tzDir == "")
81 | {
82 | if (sm_RHomePath == "")
83 | {
84 | CheckAndSetRHome();
85 | }
86 |
87 | string valueForTZDir = sm_RHomePath + "\\share\\zoneinfo";
88 | Utilities::SetEnvVariable("TZDIR", valueForTZDir);
89 | }
90 | else
91 | {
92 | LOG("TZDIR is set as: " + tzDir);
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/sample/LoopBackConnection/LoopBackConnectionOLEDB.cs:
--------------------------------------------------------------------------------
1 | //*********************************************************************
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT License.
4 | //
5 | // @File: LoopBackConnectionOLEDB.cs
6 | //
7 | // Purpose:
8 | // Connect to SQL server using the loopback connection in a Language extension environment.
9 | //
10 | //*********************************************************************
11 | using Microsoft.Data.Analysis;
12 | using Microsoft.Data.SqlClient;
13 | using Microsoft.SqlServer.CSharpExtension.SDK;
14 | using System;
15 | using System.Collections.Generic;
16 | using System.IO;
17 | using System.Text.RegularExpressions;
18 | using System.Data.OleDb;
19 |
20 | namespace UserExecutor
21 | {
22 | ///
23 | /// This class extends the AbstractSqlServerExtensionExecutor.
24 | /// This class can be used to execute custom SQL queries within the Language Extension environment.
25 | ///
26 | public class LoopBackConnectionOLEDB : AbstractSqlServerExtensionExecutor
27 | {
28 | ///
29 | /// This method overrides the Execute method from AbstractSqlServerExtensionExecutor.
30 | ///
31 | public override DataFrame Execute(DataFrame input, Dictionary sqlParams)
32 | {
33 | // Ole DB implementation
34 | // Connection string to the server..
35 | // This is a standard connection string.
36 | // Example:
37 | //string connectionstring = "Data Source=;User Id=<>;Password=<>;Initial Catalog=<>;Trusted_Connection=True;Encrypt=False;";
38 | string connectionstring = sqlParams["@connectionString"];
39 |
40 | // Create empty output DataFrame with One column
41 | //
42 | DataFrame output = new DataFrame(new StringDataFrameColumn("text", 0));
43 | using (OleDbConnection connection = new OleDbConnection(connectionstring))
44 | {
45 | connection.Open();
46 |
47 | // The SQL command that you need to execute on the SQL server.
48 | // This can be passed as a parameter as well into this method if you want to make it more dynamic.
49 | String sql = sqlParams["@query"];
50 | using (OleDbCommand command = new OleDbCommand(sql, connection))
51 | {
52 | using (OleDbDataReader reader = command.ExecuteReader())
53 | {
54 | while (reader.Read())
55 | {
56 | String outstring = "{0} {1}", reader.GetString(0), reader.GetString(1);
57 | Console.WriteLine(outstring);
58 | output.append(outstring);
59 | }
60 | }
61 | }
62 | }
63 |
64 | // Modify the parameters
65 | //
66 | sqlParams["@rowsCount"] = output.Rows.Count;
67 | sqlParams["@Status"] = "Success!";
68 |
69 | return output;
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/language-extensions/dotnet-core-CSharp/test/src/native/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required (VERSION 3.5)
2 |
3 | # This is what the final executable is going to be named
4 | #
5 | project(dotnet-core-CSharp-extension-test VERSION 1.0 LANGUAGES CXX)
6 |
7 | # All string comparisons are CASE SENSITIVE in CMAKE. Make all strings lower before comparisons!
8 | #
9 | string(TOLOWER ${PLATFORM} PLATFORM)
10 | string(TOLOWER ${CMAKE_CONFIGURATION} CMAKE_CONFIGURATION)
11 |
12 | file(TO_CMAKE_PATH ${ENL_ROOT}/extension-host EXTENSION_API_HOME)
13 | file(TO_CMAKE_PATH ${ENL_ROOT}/language-extensions/dotnet-core-CSharp DOTNETCORE_CSHARP_EXTENSION_HOME)
14 | file(TO_CMAKE_PATH ${DOTNETCORE_CSHARP_EXTENSION_HOME}/test DOTNETCORE_CSHARP_EXTENSION_TEST_HOME)
15 | file(TO_CMAKE_PATH ${DOTNETCORE_CSHARP_EXTENSION_TEST_HOME}/src/native DOTNETCORE_CSHARP_EXTENSION_TEST_SRC_DIR)
16 |
17 | # C++ unit tests code; only these files are compiled-in
18 | #
19 | file(GLOB DOTNETCORE_CSHARP_EXTENSION_TEST_SOURCE_FILES
20 | ${DOTNETCORE_CSHARP_EXTENSION_TEST_SRC_DIR}/*.cpp)
21 |
22 | add_executable(dotnet-core-CSharp-extension-test
23 | ${DOTNETCORE_CSHARP_EXTENSION_TEST_SOURCE_FILES}
24 | )
25 |
26 | target_compile_options(dotnet-core-CSharp-extension-test PRIVATE --std=c++17)
27 |
28 | # Set the DLLEXPORT variable to export symbols
29 | #
30 | add_definitions(-DWIN_EXPORT -D_WIN64 -D_WINDOWS)
31 | target_compile_definitions(dotnet-core-CSharp-extension-test PRIVATE WIN_EXPORT)
32 |
33 |
34 | file(TO_CMAKE_PATH ${ENL_ROOT}/language-extensions/dotnet-core-CSharp/test/include/ DOTNETCORE_CSHARP_EXTENSION_TEST_INCLUDE_DIR)
35 | file(TO_CMAKE_PATH ${ENL_ROOT}/build-output/dotnet-core-CSharp-extension-test/${PLATFORM}/ DOTNETCORE_CSHARP_EXTENSION_TEST_WORKING_DIR)
36 | file(TO_CMAKE_PATH ${DOTNETCORE_CSHARP_EXTENSION_TEST_WORKING_DIR}/${CMAKE_CONFIGURATION} DOTNETCORE_CSHARP_EXTENSION_TEST_INSTALL_DIR)
37 |
38 | file(TO_CMAKE_PATH ${ENL_ROOT}/packages/Microsoft.googletest.v140.windesktop.msvcstl.dyn.rt-dyn.1.8.1.3 GTEST_HOME)
39 | file(TO_CMAKE_PATH ${GTEST_HOME}/build/native/include GTEST_INCLUDE_DIR)
40 | file(TO_CMAKE_PATH ${GTEST_HOME}/lib/native/v140/windesktop/msvcstl/dyn/rt-dyn/x64/${CMAKE_CONFIGURATION} GTEST_LIB_PATH)
41 |
42 | # MDd is for debug DLL and MD is for release DLL
43 | #
44 | if (${CMAKE_CONFIGURATION} STREQUAL debug)
45 | set(COMPILE_OPTIONS ${COMPILE_OPTIONS} /MDd)
46 | find_library(GTEST_LIB gtestd ${GTEST_LIB_PATH})
47 | set(CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG} /Od)
48 | else()
49 | set(COMPILE_OPTIONS ${COMPILE_OPTIONS} /MD /O2)
50 | find_library(GTEST_LIB gtest ${GTEST_LIB_PATH})
51 | endif()
52 |
53 | # This is not a standard include path so test projects need
54 | # to add it explicitly
55 | #
56 | include_directories(
57 | "${DOTNETCORE_CSHARP_EXTENSION_TEST_INCLUDE_DIR}"
58 | "${EXTENSION_API_HOME}/include"
59 | "${DOTNETCORE_CSHARP_EXTENSION_HOME}/include"
60 | "${GTEST_INCLUDE_DIR}"
61 | )
62 |
63 | # This string comparison is case sensitive
64 | #
65 | if(${CMAKE_CONFIGURATION} STREQUAL debug)
66 | add_definitions(-D_DEBUG)
67 | endif()
68 |
69 | target_link_libraries(dotnet-core-CSharp-extension-test
70 | ${GTEST_LIB}
71 | )
72 |
73 | install(TARGETS dotnet-core-CSharp-extension-test DESTINATION ${DOTNETCORE_CSHARP_EXTENSION_TEST_INSTALL_DIR})
74 |
--------------------------------------------------------------------------------
/language-extensions/R/build/windows/restore-packages.cmd:
--------------------------------------------------------------------------------
1 | @ECHO off
2 | SETLOCAL
3 |
4 | SET ENL_ROOT=%~dp0..\..\..\..
5 | SET REXTENSION_HOME=%ENL_ROOT%\language-extensions\R
6 |
7 | REM Call the root level restore-packages
8 | REM
9 | SET PACKAGES_ROOT=%ENL_ROOT%\packages
10 | CALL %ENL_ROOT%\restore-packages.cmd
11 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to restore common nuget packages." || EXIT /b %ERRORLEVEL%
12 |
13 | REM Set DEFAULT_R_HOME
14 | REM
15 | SET R_VERSION=4.0.5
16 | SET R_INSTALLER=R-%R_VERSION%-win.exe
17 | SET DEFAULT_R_HOME=%PACKAGES_ROOT%\R-%R_VERSION%-win
18 |
19 | IF "%R_HOME%" == "" (
20 | REM If R_HOME not defined, download and install R-%R_VERSION%
21 | REM
22 | SET R_HOME=%DEFAULT_R_HOME%
23 | MKDIR %DEFAULT_R_HOME%
24 | powershell -Command "Invoke-WebRequest https://cran.r-project.org/bin/windows/base/old/%R_VERSION%/%R_INSTALLER% -OutFile %DEFAULT_R_HOME%\%R_INSTALLER%"
25 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to download R-%R_VERSION%." || EXIT /b %ERRORLEVEL%
26 | %DEFAULT_R_HOME%\%R_INSTALLER% /VERYSILENT /DIR=%DEFAULT_R_HOME%
27 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to install R-%R_VERSION%." || EXIT /b %ERRORLEVEL%
28 | ) ELSE (
29 | ECHO Using the already defined R_HOME=%R_HOME%
30 | )
31 |
32 | SET R_BIN_PATH=%R_HOME%\bin
33 |
34 | SETLOCAL enabledelayedexpansion
35 | SET R_LIBRARY_PATH=%R_HOME%\library
36 |
37 | REM Get RTools35 for mingw32-make and rtools40 for g++ v8.3.0 that works with C++17.
38 | REM
39 | SET RTOOLS_HOME=%PACKAGES_ROOT%\Rtools
40 | MKDIR %RTOOLS_HOME%
41 | powershell -Command "Invoke-WebRequest https://cran.r-project.org/bin/windows/Rtools/Rtools35.exe -OutFile %RTOOLS_HOME%\Rtools35.exe"
42 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to download Rtools3.5." || EXIT /b %ERRORLEVEL%
43 | powershell -Command "Invoke-WebRequest https://cran.r-project.org/bin/windows/Rtools/rtools40-x86_64.exe -OutFile %RTOOLS_HOME%\rtools40.exe"
44 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to download Rtools4.0." || EXIT /b %ERRORLEVEL%
45 |
46 | REM Install RTools
47 | REM
48 | "%RTOOLS_HOME%\Rtools35.exe" /VERYSILENT /DIR="C:\Rtools\"
49 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to install Rtools3.5." || EXIT /b %ERRORLEVEL%
50 | "%RTOOLS_HOME%\rtools40.exe" /VERYSILENT /DIR="C:\rtools40\"
51 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to install Rtools4.0." || EXIT /b %ERRORLEVEL%
52 |
53 | REM Install Rcpp and RInside
54 | REM Setting PATH to access make.exe
55 | REM
56 | SET PATH=C:\rtools40\usr\bin;%PATH%
57 |
58 | "%R_BIN_PATH%\R" -e "install.packages('https://cran.r-project.org/src/contrib/Archive/Rcpp/Rcpp_1.0.6.tar.gz', lib = '!R_LIBRARY_PATH:\=/!', repos = NULL, type='source')"
59 | "%R_BIN_PATH%\R" -e "stopifnot(require(Rcpp))"
60 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to install Rcpp package" || EXIT /b %ERRORLEVEL%
61 |
62 | "%R_BIN_PATH%\R" -e "install.packages('https://cran.r-project.org/src/contrib/Archive/RInside/RInside_0.2.15.tar.gz', lib = '!R_LIBRARY_PATH:\=/!', repos = NULL, , type='source')"
63 | "%R_BIN_PATH%\R" -e "stopifnot(require(RInside))"
64 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to install RInside package" || EXIT /b %ERRORLEVEL%
65 | SETLOCAL disabledelayedexpansion
66 |
67 | EXIT /b %ERRORLEVEL%
68 |
69 | :CHECKERROR
70 | IF %1 NEQ 0 (
71 | ECHO %2
72 | EXIT /b %1
73 | )
74 |
75 | EXIT /b 0
76 |
--------------------------------------------------------------------------------
/language-extensions/python/test/include/PythonLibraryTests.h:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // Copyright (C) Microsoft Corporation.
3 | // Distributed under the Boost Software License, Version 1.0.
4 | // (See accompanying file LICENSE_1_0.txt or copy at
5 | // https://www.boost.org/LICENSE_1_0.txt)
6 | //
7 | // @File: PythonLibraryTests.h
8 | //
9 | // Purpose:
10 | // Define the gtest overrides and the External Library tests
11 | //
12 | //*************************************************************************************************
13 | #pragma once
14 | #include "Common.h"
15 | #ifdef _WIN64
16 | #include
17 | namespace fs = std::filesystem;
18 | #else
19 | #include
20 | namespace fs = std::experimental::filesystem;
21 | #endif
22 |
23 | namespace LibraryApiTests
24 | {
25 | // All the tests in the LibraryApiTests suite run one after the other
26 | //
27 | class ExternalLibraryApiTests : public ::testing::Test
28 | {
29 | protected:
30 | // Code here will be called immediately after the constructor (right
31 | // before each test).
32 | //
33 | void SetUp() override;
34 |
35 | // Code here will be called immediately after each test (right
36 | // before the destructor).
37 | //
38 | void TearDown() override;
39 |
40 | // Set up default, valid variables for use in tests
41 | //
42 | void SetupVariables();
43 |
44 | // Call Cleanup on the PythonExtension.
45 | // Testing if Cleanup is implemented correctly.
46 | //
47 | void DoCleanup();
48 |
49 | // Cleanup sys.modules in python to remove import traces
50 | //
51 | void CleanModules(std::string extLibName, std::string moduleName);
52 |
53 | // Install and test a package
54 | //
55 | void InstallAndTest(
56 | std::string extLibName,
57 | std::string moduleName,
58 | std::string pathToPackage,
59 | std::string installDir,
60 | std::string expectedVersion,
61 | std::string expectedLocation = "",
62 | bool successfulInstall = true,
63 | bool successfulImport = true);
64 |
65 | // Uninstall and test a package
66 | //
67 | void UninstallAndTest(
68 | std::string extLibName,
69 | std::string moduleName,
70 | std::string installDir,
71 | bool otherInstallationExists = false);
72 |
73 | // Initialize pythonextension for library management
74 | //
75 | void Initialize();
76 |
77 | // Filesystem path to the packages we will install
78 | //
79 | fs::path m_packagesPath;
80 |
81 | // Some temp paths for public and private libraries
82 | //
83 | std::string m_libraryPath = "testInstallPkgs";
84 | std::string m_publicLibraryPath;
85 | std::string m_privateLibraryPath;
86 | std::string m_pathToPython;
87 |
88 | // The boost python module; python will run in this object
89 | //
90 | boost::python::object m_mainModule;
91 |
92 | // The boost python namespace; backup dictionary containing all builtins
93 | //
94 | boost::python::dict m_backupNamespace;
95 |
96 | // The main namespace. We use this for all execution
97 | //
98 | boost::python::dict m_mainNamespace;
99 |
100 | };
101 | }
102 |
--------------------------------------------------------------------------------
/language-extensions/R/test/build/windows/build-RExtension-test.cmd:
--------------------------------------------------------------------------------
1 | @ECHO off
2 | SETLOCAL
3 |
4 | REM Set environment variables
5 | REM
6 | SET ENL_ROOT=%~dp0..\..\..\..\..
7 | SET REXTENSIONTEST_HOME=%ENL_ROOT%\language-extensions\R\test
8 | SET REXTENSIONTEST_WORKING_DIR=%ENL_ROOT%\build-output\RExtension-test\windows
9 | SET PACKAGES_ROOT=%ENL_ROOT%\packages
10 | SET DEFAULT_R_HOME=%PACKAGES_ROOT%\R-4.0.5-win
11 | SET DEFAULT_CMAKE_ROOT=%PACKAGES_ROOT%\CMake-win64.3.15.5
12 |
13 | REM Find R_HOME and CMAKE_ROOT from user, or set to default.
14 | REM Error code 203 is ENVVAR_NOT_FOUND.
15 | REM
16 | SET ENVVAR_NOT_FOUND=203
17 |
18 | IF "%R_HOME%" == "" (
19 | IF EXIST %DEFAULT_R_HOME% (
20 | SET R_HOME=%DEFAULT_R_HOME%
21 | ) ELSE (
22 | CALL :CHECKERROR %ENVVAR_NOT_FOUND% "Error: R_HOME variable must be set to build RExtension-test" || EXIT /b %ENVVAR_NOT_FOUND%
23 | )
24 | )
25 |
26 | IF "%CMAKE_ROOT%" == "" (
27 | IF EXIST %DEFAULT_CMAKE_ROOT% (
28 | SET CMAKE_ROOT=%DEFAULT_CMAKE_ROOT%
29 | ) ELSE (
30 | CALL :CHECKERROR %ENVVAR_NOT_FOUND% "Error: CMAKE_ROOT variable must be set to build RExtension-test" || EXIT /b %ENVVAR_NOT_FOUND%
31 | )
32 | )
33 |
34 | REM Create build working directory
35 | REM
36 | RMDIR /s /q %REXTENSIONTEST_WORKING_DIR%
37 | MKDIR %REXTENSIONTEST_WORKING_DIR%
38 |
39 | :LOOP
40 |
41 | REM Set cmake config to first arg
42 | REM
43 | SET CMAKE_CONFIGURATION=%1
44 |
45 | REM The string comparison for CMAKE_CONFIGURATION is case-insensitive.
46 | REM
47 | IF NOT DEFINED CMAKE_CONFIGURATION (SET CMAKE_CONFIGURATION=release)
48 | IF /I NOT %CMAKE_CONFIGURATION%==debug (SET CMAKE_CONFIGURATION=release)
49 |
50 | SET BUILD_OUTPUT=%REXTENSIONTEST_WORKING_DIR%\%CMAKE_CONFIGURATION%
51 | MKDIR %BUILD_OUTPUT%
52 | PUSHD %BUILD_OUTPUT%
53 |
54 | REM Make sure g++ is in the PATH.
55 | REM Do not enclose the C:\Rtools\mingw_64\bin path in quotes - cmake test fails
56 | REM Also need to have R_HOME\bin\x64 in the PATH so that linker finds definitions for R functions.
57 | REM
58 | SET PATH=C:\rtools40\mingw64\bin;C:\Rtools\mingw_64\bin;%R_HOME%\bin\x64;%PATH%
59 |
60 | ECHO "[INFO] Generating RExtension test project build files using CMAKE_CONFIGURATION=%CMAKE_CONFIGURATION%"
61 |
62 | REM Call cmake
63 | call "%CMAKE_ROOT%\bin\cmake.exe" ^
64 | -G "MinGW Makefiles" ^
65 | -DCMAKE_INSTALL_PREFIX:PATH="%REXTENSIONTEST_WORKING_DIR%\\%CMAKE_CONFIGURATION%" ^
66 | -DENL_ROOT="%ENL_ROOT%" ^
67 | -DCMAKE_MAKE_PROGRAM=mingw32-make ^
68 | -DCMAKE_BUILD_TYPE=%CMAKE_CONFIGURATION% ^
69 | -DPLATFORM=windows ^
70 | -DR_HOME="%R_HOME%" ^
71 | "%REXTENSIONTEST_HOME%\src"
72 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to generate make files for CMAKE_CONFIGURATION=%CMAKE_CONFIGURATION%" || EXIT /b %ERRORLEVEL%
73 |
74 | ECHO "[INFO] Building RExtension test project using CMAKE_CONFIGURATION=%CMAKE_CONFIGURATION%"
75 | REM Call cmake build
76 | REM
77 | CALL "mingw32-make.exe" -j all
78 | CALL :CHECKERROR %ERRORLEVEL% "Error: Failed to build RExtension-test for CMAKE_CONFIGURATION=%CMAKE_CONFIGURATION%" || EXIT /b %ERRORLEVEL%
79 |
80 | REM Advance arg passed to build-RExtension-test.cmd
81 | REM
82 | SHIFT
83 |
84 | REM Continue building using more configs until argv has been exhausted
85 | REM
86 | IF NOT "%~1"=="" GOTO LOOP
87 |
88 | EXIT /b %ERRORLEVEL%
89 |
90 | :CHECKERROR
91 | IF %1 NEQ 0 (
92 | ECHO %2
93 | EXIT /b %1
94 | )
95 |
96 | EXIT /b 0
97 |
--------------------------------------------------------------------------------
/language-extensions/python/src/linux/PythonExtensionUtils_linux.cpp:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // Copyright (C) Microsoft Corporation.
3 | // Distributed under the Boost Software License, Version 1.0.
4 | // (See accompanying file LICENSE_1_0.txt or copy at
5 | // https://www.boost.org/LICENSE_1_0.txt)
6 | //
7 | // @File: PythonExtensionUtils_linux.cpp
8 | //
9 | // Purpose:
10 | // Linux specific utility functions for Python Extension
11 | //
12 | //*************************************************************************************************
13 |
14 | #include
15 | #include
16 |
17 | #include "Logger.h"
18 | #include "PythonExtensionUtils.h"
19 |
20 | namespace fs = std::experimental::filesystem;
21 |
22 | const CHAR *GuidFormat = "%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X";
23 |
24 | //--------------------------------------------------------------------------------------------------
25 | // Name: PythonExtensionUtils::GetEnvVariable
26 | //
27 | // Description:
28 | // Get the value of an environment variable
29 | //
30 | // Returns:
31 | // String value of the environment variable requested
32 | //
33 | std::string PythonExtensionUtils::GetEnvVariable(const std::string &envVarName)
34 | {
35 | char* envVarValue;
36 | envVarValue = getenv(envVarName.c_str());
37 |
38 | if (envVarValue == NULL)
39 | {
40 | throw std::runtime_error("Error while loading " + envVarName);
41 | }
42 |
43 | return std::string(envVarValue);
44 | }
45 |
46 | //--------------------------------------------------------------------------------------------------
47 | // Name: PythonExtensionUtils::ConvertGuidToString
48 | //
49 | // Description:
50 | // Converts a SQLGUID to a string
51 | //
52 | // Returns:
53 | // string of the guid
54 | //
55 | std::string PythonExtensionUtils::ConvertGuidToString(const SQLGUID *guid)
56 | {
57 | // 32 hex chars + 4 hyphens + null terminator, so 37 characters.
58 | //
59 | char guidString[37];
60 |
61 | snprintf(guidString, sizeof(guidString) / sizeof(guidString[0]),
62 | GuidFormat,
63 | static_cast(guid->Data1), guid->Data2, guid->Data3,
64 | guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
65 | guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
66 |
67 | std::string s(guidString);
68 |
69 | return s;
70 | }
71 |
72 | //--------------------------------------------------------------------------------------------------
73 | // Name: PythonExtensionUtils::FreeDLL
74 | //
75 | // Description:
76 | // Close an open dll handle
77 | //
78 | void PythonExtensionUtils::FreeDLL(void *pDll)
79 | {
80 | if (pDll != nullptr)
81 | {
82 | dlclose(pDll);
83 | }
84 | }
85 |
86 | //--------------------------------------------------------------------------------------------------
87 | // Name: PythonExtensionUtils::GetEnvVariable
88 | //
89 | // Description:
90 | // Get the path to the python executable
91 | //
92 | // Returns:
93 | // String value of the python executable path
94 | //
95 | std::string PythonExtensionUtils::GetPathToPython()
96 | {
97 | fs::path pathToPython = fs::path("python3.12");
98 | return pathToPython.string();
99 | }
100 |
--------------------------------------------------------------------------------
/language-extensions/python/test/src/PythonInitColumnTests.cpp:
--------------------------------------------------------------------------------
1 | //*************************************************************************************************
2 | // Copyright (C) Microsoft Corporation.
3 | // Distributed under the Boost Software License, Version 1.0.
4 | // (See accompanying file LICENSE_1_0.txt or copy at
5 | // https://www.boost.org/LICENSE_1_0.txt)
6 | //
7 | // @File: PythonInitColumnTests.cpp
8 | //
9 | // Purpose:
10 | // Test the Python extension columns using the Extension API
11 | //
12 | //*************************************************************************************************
13 | #include "PythonExtensionApiTests.h"
14 |
15 | namespace ExtensionApiTest
16 | {
17 | // Name: InitColumnTest
18 | //
19 | // Description:
20 | // Test InitColumn() API with valid values
21 | //
22 | TEST_F(PythonExtensionApiTests, InitColumnTest)
23 | {
24 | InitializeSession(0, // paramsNumber
25 | 1); // inputSchemaColumns
26 |
27 | SQLCHAR * columnName = static_cast(
28 | static_cast(const_cast("Column1")));
29 | SQLSMALLINT columnNameLength = 7;
30 | SQLRETURN result = InitColumn(
31 | *m_sessionId,
32 | m_taskId,
33 | 0, // Column Number
34 | columnName,
35 | columnNameLength,
36 | SQL_C_SLONG, // Data Type
37 | m_IntSize, // Column Size
38 | 0, // Decimal Digits
39 | 1, // Nullable
40 | -1, // PartitionByNumber
41 | -1 // OrderByNumber
42 | );
43 | EXPECT_EQ(result, SQL_SUCCESS);
44 | }
45 |
46 | //
47 | // Negative Tests
48 | //
49 |
50 | // Name: InitInvalidColumnTest
51 | //
52 | // Description:
53 | // Test InitColumn() API with null column name
54 | //
55 | TEST_F(PythonExtensionApiTests, InitInvalidColumnTest)
56 | {
57 | InitializeSession(0, // paramsNumber
58 | 1); // inputSchemaColumns
59 |
60 | SQLRETURN result = InitColumn(
61 | *m_sessionId,
62 | m_taskId,
63 | 0, // Column Number
64 | nullptr, // Column Name
65 | 0, // Column Name Length
66 | SQL_C_SLONG, // Data Type
67 | m_IntSize, // Column Size
68 | 0, // Decimal Digits
69 | 1, // Nullable
70 | -1, // PartitionByNumber
71 | -1 // OrderByNumber
72 | );
73 | EXPECT_EQ(result, SQL_ERROR);
74 | }
75 |
76 | // Name: InitInvalidColumnNumberTest
77 | //
78 | // Description:
79 | // Test InitColumn() API with bad column numbers (too big)
80 | //
81 | TEST_F(PythonExtensionApiTests, InitInvalidColumnNumberTest)
82 | {
83 | InitializeSession(1);
84 |
85 | SQLCHAR * columnName = static_cast(
86 | static_cast(const_cast("Column1")));
87 | SQLSMALLINT columnNameLength = 7;
88 |
89 | SQLRETURN result = InitColumn(
90 | *m_sessionId,
91 | m_taskId,
92 | 2, // column number greater than initialized columns
93 | columnName,
94 | columnNameLength,
95 | SQL_C_SLONG, // Data Type
96 | m_IntSize, // Column Size
97 | 0, // Decimal Digits
98 | 1, // Nullable
99 | -1, // PartitionByNumber
100 | -1 // OrderByNumber
101 | );
102 | EXPECT_EQ(result, SQL_ERROR);
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/language-extensions/R/include/REnvironment.h:
--------------------------------------------------------------------------------
1 | //**************************************************************************************************
2 | // RExtension : A language extension implementing the SQL Server
3 | // external language communication protocol for R.
4 | // Copyright (C) 2020 Microsoft Corporation.
5 | //
6 | // This file is part of RExtension.
7 | //
8 | // RExtension is free software: you can redistribute it and/or modify
9 | // it under the terms of the GNU General Public License as published by
10 | // the Free Software Foundation, either version 3 of the License, or
11 | // (at your option) any later version.
12 | //
13 | // RExtension is distributed in the hope that it will be useful,
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | // GNU General Public License for more details.
17 | //
18 | // You should have received a copy of the GNU General Public License
19 | // along with RExtension. If not, see .
20 | //
21 | // @File: REnvironment.h
22 | //
23 | // Purpose:
24 | // Class to keep the global embedded R environment.
25 | //
26 | //**************************************************************************************************
27 |
28 | #pragma once
29 |
30 | //--------------------------------------------------------------------------------------------------
31 | // Name: REnvironment
32 | //
33 | // Description:
34 | // Global class storing the global embedded R environment.
35 | //
36 | class REnvironment
37 | {
38 | public:
39 |
40 | // Initializes this global class
41 | //
42 | static void Init(SQLULEN extensionParamsLength);
43 |
44 | // Cleans up this global class
45 | //
46 | static void Cleanup();
47 |
48 | // Gets the global embedded R environment as an RInside object pointer.
49 | //
50 | static RInside* EmbeddedREnvironment()
51 | {
52 | if (sm_embeddedREnvPtr == nullptr)
53 | {
54 | throw std::runtime_error("Embedded R environment has not been initialized.");
55 | }
56 |
57 | return sm_embeddedREnvPtr.get();
58 | }
59 |
60 | // Encloses the given script in a try catch block.
61 | //
62 | static std::string GetScriptWithTryCatch(const std::string &script);
63 |
64 | private:
65 |
66 | // An unique pointer to the embedded R environment via RInside.
67 | // We execute all R scripts in this environment and there can only be a single
68 | // instance of RInside in the extension.
69 | // Avoid using a shared pointer since it leads to data races.
70 | //
71 | static std::unique_ptr sm_embeddedREnvPtr;
72 |
73 | // Original library path
74 | //
75 | static std::unique_ptr sm_originalPath;
76 | };
77 |
78 | #ifdef _WIN32
79 | #define REXTENSION_INTERFACE __declspec(dllexport)
80 | #elif __linux__
81 | #define REXTENSION_INTERFACE __attribute__((visibility("default")))
82 | #else
83 | #define REXTENSION_INTERFACE
84 | #endif
85 |
86 | #ifdef __cplusplus
87 | extern "C" {
88 | #endif/* __cplusplus */
89 |
90 | // Simply executes the given script.
91 | //
92 | REXTENSION_INTERFACE void ExecuteScript(const std::string &script);
93 |
94 | // Executes the given script and returns the result as an SEXP pointer.
95 | //
96 | REXTENSION_INTERFACE SEXP ExecuteScriptAndGetResult(const std::string &script);
97 |
98 | #ifdef __cplusplus
99 | } /* End of extern "C" { */
100 | #endif/* __cplusplus */
101 |
--------------------------------------------------------------------------------