From 5e9c891c7c6402b42e4ad200af5fc81c8571b70c Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 11:58:17 +0100 Subject: [PATCH 01/37] Refactor code structure for improved readability and maintainability --- .github/workflows/README.md | 89 ++++++++++++++++++++++++ .github/workflows/release.yml | 116 +++++++++++++++++++++++++++++++ FastWrappers-TSQL.sql | 124 ++++++++++++++++++++++++++++++++++ README.md | 22 ++++++ 4 files changed, 351 insertions(+) create mode 100644 .github/workflows/README.md create mode 100644 .github/workflows/release.yml create mode 100644 FastWrappers-TSQL.sql diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 0000000..27c7ac9 --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,89 @@ +# Release Workflow + +This GitHub Actions workflow automates the creation of releases for the FastWrappers-TSQL project. + +## Trigger + +The workflow is automatically triggered when creating a new tag starting with `v` (e.g., `v0.3.3`). + +## Generated Artifacts + +The workflow generates 4 types of artifacts for different installation methods: + +1. **FastWrappers-TSQL.dacpac** - Data-tier Application Package + - Recommended for Visual Studio / SQL Server Data Tools + - Enables controlled deployment with drift detection + +2. **FastWrappers-TSQL.bacpac** - Binary Application Package + - For import/export between servers + - Contains the schema + compiled assembly + +3. **FastWrappers-TSQL.bak** - SQL Server Backup + - Compatible with SQL Server 2016+ (Compatibility Level 130) + - Direct restore via SSMS or T-SQL + +4. **FastWrappers-TSQL.sql** - Pure SQL Script + - Executable via sqlcmd or SSMS + - **Automatically generated from DACPAC with up-to-date binary** + - Contains the compiled assembly in inline hexadecimal format + +## Build Process + +1. **Checkout** source code +2. **Setup** MSBuild and NuGet +3. **Build** SQL project in Release mode +4. **Deploy** temporarily to SQL LocalDB +5. **Generate** artifacts: + - BACPAC via SqlPackage export + - BAK via BACKUP DATABASE (with compression) + - DACPAC copied from bin/Release + - **SQL script generated from DACPAC (contains up-to-date compiled binary)** +6. **Create** GitHub release with all artifacts + +## How to Create a New Release + +### 1. Update the Version + +Edit [Properties/AssemblyInfo.cs](../Properties/AssemblyInfo.cs): +```csharp +[assembly: AssemblyVersion("0.3.3.0")] +[assembly: AssemblyFileVersion("0.3.3.0")] +``` + +Optional: Update [FastWrappers_TSQL.sqlproj](../FastWrappers_TSQL.sqlproj): +```xml +0.3.3.0 +``` + +### 2. Commit and Tag + +```bash +git add Properties/AssemblyInfo.cs +git commit -m "Bump version to 0.3.3" +git tag v0.3.3 +git push origin main +git push origin v0.3.3 +``` + +### 3. Verify the Release + +1. Go to https://github.com/aetperf/FastWrappers-TSQL/actions +2. Check that the "Create Release Artifacts" workflow is running +3. Once completed, verify the release at https://github.com/aetperf/FastWrappers-TSQL/releases + +## Troubleshooting + +### Workflow fails during build + +- Verify that the project compiles locally in Release mode +- Check NuGet dependencies + +### SqlPackage cannot find the assembly + +- Verify that the DACPAC is correctly generated in `bin/Release/` +- Verify that the file is signed (AetPCLRSign.pfx.snk) + +### Backup fails + +- SQL LocalDB may need more time to start +- Increase the `Start-Sleep` after LocalDB startup diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..2cdf4c4 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,116 @@ +name: Create Release Artifacts + +on: + push: + tags: + - 'v*.*.*' + +jobs: + build-and-release: + runs-on: windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v2 + + - name: Setup NuGet + uses: nuget/setup-nuget@v2 + + - name: Restore NuGet packages + run: nuget restore FastWrappers-TSQL.sln + + - name: Build SQL Project + run: msbuild FastWrappers_TSQL.sqlproj /p:Configuration=Release /p:Platform="Any CPU" + + - name: Setup SQL Server (LocalDB) + shell: powershell + run: | + # Start SQL LocalDB + sqllocaldb create MSSQLLocalDB + sqllocaldb start MSSQLLocalDB + + # Wait for SQL Server to be ready + Start-Sleep -Seconds 10 + + - name: Deploy Database and Create Artifacts + shell: powershell + run: | + # Variables + $serverInstance = "(localdb)\MSSQLLocalDB" + $dbName = "FastWrappers-TSQL" + $dacpacPath = "bin\Release\FastWrappers_TSQL.dacpac" + $bacpacPath = "bin\Release\FastWrappers-TSQL.bacpac" + $bakPath = "bin\Release\FastWrappers-TSQL.bak" + + # Download SqlPackage if needed + if (!(Test-Path "SqlPackage\SqlPackage.exe")) { + Write-Host "Downloading SqlPackage..." + Invoke-WebRequest -Uri "https://aka.ms/sqlpackage-windows" -OutFile "SqlPackage.zip" + Expand-Archive -Path "SqlPackage.zip" -DestinationPath "SqlPackage" + } + + $sqlPackage = "SqlPackage\SqlPackage.exe" + + # Deploy the DACPAC to create the database + Write-Host "Deploying DACPAC to create database..." + & $sqlPackage /Action:Publish /SourceFile:$dacpacPath /TargetServerName:$serverInstance /TargetDatabaseName:$dbName /p:IncludeCompositeObjects=True + + # Wait for deployment to complete + Start-Sleep -Seconds 5 + + # Export to BACPAC + Write-Host "Exporting to BACPAC..." + & $sqlPackage /Action:Export /SourceServerName:$serverInstance /SourceDatabaseName:$dbName /TargetFile:$bacpacPath + + # Create .bak file with compatibility level for SQL Server 2016 + Write-Host "Creating SQL Server 2016 compatible backup..." + sqlcmd -S $serverInstance -Q "ALTER DATABASE [$dbName] SET COMPATIBILITY_LEVEL = 130; BACKUP DATABASE [$dbName] TO DISK = N'$PWD\$bakPath' WITH COMPRESSION, STATS = 10" + + # Generate SQL script from DACPAC (includes the compiled binary) + Write-Host "Generating SQL script from DACPAC..." + $generatedSqlPath = "bin\Release\FastWrappers-TSQL.sql" + & $sqlPackage /Action:Script /SourceFile:$dacpacPath /OutputPath:$generatedSqlPath /p:IncludeCompositeObjects=True + + # Copy DACPAC with proper name + Write-Host "Copying DACPAC with release name..." + Copy-Item $dacpacPath "bin\Release\FastWrappers-TSQL.dacpac" + + Write-Host "All artifacts created successfully!" + + - name: Get version from tag + id: get_version + shell: bash + run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT + + - name: Create Release + id: create_release + uses: softprops/action-gh-release@v1 + with: + name: Release v${{ steps.get_version.outputs.VERSION }} + body: | + ## FastWrappers-TSQL v${{ steps.get_version.outputs.VERSION }} + + ### Installation Methods + + This release provides multiple installation options: + + - **FastWrappers-TSQL.dacpac** - Data-tier Application Package (recommended for Visual Studio / SQL Server Data Tools) + - **FastWrappers-TSQL.bacpac** - Binary Application Package (for import/export between servers) + - **FastWrappers-TSQL.bak** - SQL Server Backup (compatible with SQL Server 2016+, restore using SSMS) + - **FastWrappers-TSQL.sql** - Pure SQL Script (execute using sqlcmd or SSMS) + + ### Usage + + See [README.md](https://github.com/${{ github.repository }}/blob/main/README.md) for usage examples. + files: | + bin/Release/FastWrappers-TSQL.dacpac + bin/Release/FastWrappers-TSQL.bacpac + bin/Release/FastWrappers-TSQL.bak + bin/Release/FastWrappers-TSQL.sql + draft: false + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/FastWrappers-TSQL.sql b/FastWrappers-TSQL.sql new file mode 100644 index 0000000..ae295b6 --- /dev/null +++ b/FastWrappers-TSQL.sql @@ -0,0 +1,124 @@ +/***************************************************************************************************** + * REFERENCE FILE - DO NOT USE IN PRODUCTION + * =================================================================================================== + * + * This SQL file contains a static compiled binary that may be outdated. + * + * To deploy FastWrappers-TSQL, download the automatically generated SQL file from: + * https://github.com/aetperf/FastWrappers-TSQL/releases/latest + * + * The release SQL file is automatically generated by GitHub Actions and contains + * the up-to-date compiled binary (CREATE ASSEMBLY ... FROM 0x4D5A9000...). + * + * This file is kept only as a structure reference. + * + *****************************************************************************************************/ + +USE [FastWrappers-TSQL] +GO +/****** Object: DatabaseRole [FastTransfer_Executor] Script Date: 2025-10-13 23:19:40 ******/ +CREATE ROLE [FastTransfer_Executor] +GO +/****** Object: SqlAssembly [FastWrappers_TSQL] Script Date: 2025-10-13 23:19:40 ******/ +CREATE ASSEMBLY [FastWrappers_TSQL] +FROM 0x4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C0103007968ED680000000000000000E00022200B013000004400000008000000000000CE62000000200000008000000000001000200000000200000400000000000000060000000000000000C0000000020000A20801000300608500001000001000000000100000100000000000001000000000000000000000007C6200004F00000000800000440400000000000000000000000000000000000000A000000C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E7465787400000008430000002000000044000000020000000000000000000000000000200000602E7273726300000044040000008000000006000000460000000000000000000000000000400000402E72656C6F6300000C00000000A0000000020000004C00000000000000000000000000004000004200000000000000000000000000000000B0620000000000004800000002000500EC330000102E000009000000000000000000000000000000FC610000800000000000000000000000000000000000000000000000000000000000000000000000860F00280F00000A2C067E1000000A2A0F00281100000A2805000006731200000A2A000013302200B600000001000011140A0F02280F00000A2D0C04281300000A28060000060A140B0F08280F00000A2D0D0E08281300000A28060000060B140C0F0F280F00000A2D0D0E0F281300000A28060000060C140D0F13280F00000A2D0D0E13281300000A28060000060D020306281400000A050E040E050E060E0707281400000A0E090E0A0E0B0E0C0E0D0E0E08281400000A0E100E110E1209281400000A0E140E150E160E170E180E190E1A0E1B0E1C0E1D0E1E0E1F0E200E2128030000062A00001B3006006E100000020000110F00280F00000A2D0E0F00281100000A6F1500000A2B01140A0F01280F00000A2D130F01281100000A6F1500000A6F1600000A2B01140B0F02280F00000A2D0E0F02281100000A6F1500000A2B01140C0F03280F00000A2D0E0F03281100000A6F1500000A2B01140D0F04280F00000A2D0E0F04281100000A6F1500000A2B011413040F05280F00000A2D0E0F05281100000A6F1500000A2B011413050F06281700000A2D090F06281800000A2B011613060F07280F00000A2D0E0F07281100000A6F1500000A2B011413070F08280F00000A2D0E0F08281100000A6F1500000A2B011413080F09280F00000A2D0E0F09281100000A6F1500000A2B011413090F0A280F00000A2D0E0F0A281100000A6F1500000A2B0114130A0F0B280F00000A2D0E0F0B281100000A6F1500000A2B0114130B0F0C280F00000A2D0E0F0C281100000A6F1500000A2B0114130C0F0D280F00000A2D0E0F0D281100000A6F1500000A2B0114130D0F0E280F00000A2D130F0E281100000A6F1500000A6F1600000A2B0114130E0F0F280F00000A2D0E0F0F281100000A6F1500000A2B0114130F0F10280F00000A2D0E0F10281100000A6F1500000A2B011413100F11281700000A2D090F11281800000A2B011613110F12280F00000A2D0E0F12281100000A6F1500000A2B011413120F13280F00000A2D0E0F13281100000A6F1500000A2B011413130F14280F00000A2D0E0F14281100000A6F1500000A2B011413140F15280F00000A2D0E0F15281100000A6F1500000A2B011413150F16280F00000A2D0E0F16281100000A6F1500000A2B011413160F17280F00000A2D0E0F17281100000A6F1500000A2B011413170F18281900000A2D0E0F18281A00000A731B00000A2B0A122DFE150100001B112D13180F19280F00000A2D0E0F19281100000A6F1500000A2B011413190F1A280F00000A2D0E0F1A281100000A6F1500000A2B0114131A0F1B281900000A2D0E0F1B281A00000A731B00000A2B0A122DFE150100001B112D131B0F1C280F00000A2D0E0F1C281100000A6F1500000A2B0114131C0F1D280F00000A2D0E0F1D281100000A6F1500000A2B0114131D0F1E280F00000A2D0E0F1E281100000A6F1500000A2B0114131E0F1F281700000A2D090F1F281800000A2D03162B0117131F0F20280F00000A2D0E0F20281100000A6F1500000A2B01141320720100007013210F21280F00000A2D5E0F21281100000A6F1500000A6F1600000A132E1A8D2000000125167219000070A225177225000070A225187201000070A225197235000070A2112E280100002B162F177241000070112E7269000070281D00000A731E00000A7A112E132106281F00000A2C0B7226010070731E00000A7A1F0D8D20000001251672D1010070A2251772E7010070A2251872F5010070A22519720F020070A2251A7219020070A2251B7225020070A2251C7231020070A2251D723D020070A2251E7247020070A2251F097253020070A2251F0A7261020070A2251F0B726F020070A2251F0C727B020070A21322112207280100002B162F3C1B8D200000012516728D020070A2251707A2251872CD020070A2251972FB0200701122282000000AA2251A7201030070A2282100000A731E00000A7A1F0A8D2000000125167205030070A2251772E7010070A225187223030070A225197235030070A2251A7243030070A2251B7257030070A2251C7265030070A2251D7275030070A2251E7261020070A2251F09727B020070A213231123110E280100002B162F3D1B8D2000000125167289030070A22517110EA2251872CD020070A2251972FB0200701123282000000AA2251A7201030070A2282100000A731E00000A7A08282200000A16FE01132411242C3709282200000A2C241109282200000A2C1B1107282200000A2C121108282200000A2C091104282200000A2D5C72C9030070731E00000A7A09282200000A2C141104282200000A2C0B7274040070731E00000A7A1109282200000A2C0B7211050070731E00000A7A11062D1D1107282200000A2D091108282200000A2C0B7291050070731E00000A7A161325110A282200000A2D06112517581325110B282200000A2D06112517581325110C282200000A2D0F110D282200000A2D0611251758132511252D0B7218060070731E00000A7A16110A282200000A2D06112517581325110B282200000A2D0611251758132517310B72C3060070731E00000A7A110F282200000A16FE01132611262C2F1110282200000A2C1B1114282200000A2C121112282200000A2C091113282200000A2D547221070070731E00000A7A1110282200000A2C0B72C4070070731E00000A7A1114282200000A2C0B7238080070731E00000A7A11112D1D1112282200000A2D091113282200000A2C0B72B0080070731E00000A7A1115282200000A2D091116282200000A2C0B7237090070731E00000A7A1119282200000A16FE011327112739E10000001E8D200000012516728D090070A225177297090070A2251872A5090070A2251972BB090070A2251A72CB090070A2251B72D7090070A2251C72E1090070A2251D72ED090070A21119280100002B162F1772050A0070111972290A0070281D00000A731E00000A7A1119728D0900706F2300000A2D6C111972970900706F2300000A2D2A111972A50900706F2300000A2D1C111972BB0900706F2300000A2D0E111972CB0900706F2300000A2C20111A282200000A2C1772340B0070111972560B0070281D00000A731E00000A7A121B282400000A2D0B72AC0B0070731E00000A7A1117282200000A16FE012C37188D20000001251672330C0070A2251772410C0070A21117280100002B162F1772530C00701117727B0C0070281D00000A731E00000A7A111C282200000A16FE01132811282C37188D200000012516720C0D0070A22517721E0D0070A2111C280100002B162F1772280D0070111C72520D0070281D00000A731E00000A7A061329112972DF0D00701B6F2500000A2D50112972010E00701B6F2500000A2D411129721B0E00706F2600000A2D251129721F0E00706F2600000A2D1711297E2700000A132F122F282800000A282900000A1329112972DF0D0070282900000A13297E2A00000A132A112A72230E0070072804000006281D00000A132A11242C19112A72550E0070082804000006281D00000A132A38B000000009282200000A2D34112A72850E0070092804000006281D00000A132A1105282200000A2D2C112A72A70E007011052804000006281D00000A132A2B15112A72CD0E007011042804000006281D00000A132A11062C10112A72E90E0070282900000A132A2B361B8D200000012516112AA22517720B0F0070A2251811072804000006A2251972290F0070A2251A11082804000006A2282100000A132A112A724F0F007011092804000006281D00000A132A110A282200000A2D17112A72750F0070110A2804000006281D00000A132A2B1E110B282200000A2D15112A72910F0070110B2804000006281D00000A132A110D282200000A2D33110C282200000A2D2A112A72A50F0070110C2804000006281D00000A132A112A72C70F0070110D2804000006281D00000A132A112A72E70F0070110E2804000006281D00000A132A11262C17112A7219100070110F2804000006281D00000A132A2B74112A724910007011102804000006281D00000A132A11112C10112A726B100070282900000A132A2B361B8D200000012516112AA22517728D100070A2251811122804000006A2251972AB100070A2251A11132804000006A2282100000A132A112A72D110007011142804000006281D00000A132A112A72F710007011152804000006281D00000A132A112A721911007011162804000006281D00000A132A1117282200000A2D15112A723911007011172804000006281D00000A132A1218282400000A2C1F112A72531100701218282B00000A8C26000001282C00000A282900000A132A11273994000000112A727511007011192804000006281D00000A132A1119728D0900701B6F2D00000A2D701119728B1100701B6F2D00000A2D2D111972991100701B6F2D00000A2D1E111972AF1100701B6F2D00000A2D0F111972BF1100701B6F2D00000A2C15112A72CB110070111A2804000006281D00000A132A112A72FB110070121B282B00000A8C26000001282C00000A282900000A132A11282C15112A7217120070111C2804000006281D00000A132A111D282200000A2D15112A7233120070111D2804000006281D00000A132A111E282200000A2D15112A7247120070111E2804000006281D00000A132A1120282200000A2D15112A726912007011202804000006281D00000A132A1121282200000A2D15112A728112007011212804000006281D00000A132A112A6F1500000A132A112A132B112B729B12007072D1120070282E00000A132B112B7209130070723F130070282E00000A132B112B727713007072B7130070282E00000A132B112B72F91300707239140070282E00000A132B111F2C37282F00000A1B8D200000012516727B140070A225171129A2251872A7140070A22519112BA2251A283000000AA2282100000A6F3100000A733200000A2511296F3300000A25112A6F3400000A25166F3500000A25176F3600000A25176F3700000A25176F3800000A132C112C283900000A133011306F3A00000A6F3B00000A133111306F3C00000A6F3B00000A133211306F3D00000A11306F3E00000A1333111F2C4F1131282200000A2D4620A00F0000133E16133F2B2F1131113F113E11316F3F00000A113F59284000000A6F4100000A1340282F00000A11406F3100000A113F113E58133F113F11316F3F00000A32C611316F3F00000A20B80B00003116113111316F3F00000A20B80B0000596F4200000A1331113172AB140070284300000A6F4400000A176F4500000A6F4600000A1334113172D9140070284300000A6F4400000A176F4500000A6F4600000A13351131720D150070284300000A6F4400000A176F4500000A6F4600000A13361131723D150070284300000A6F4400000A176F4500000A6F4600000A13371F098D310000012516726F1500701F0C20800000006A734700000AA22517728D1500701F0C20800000006A734700000AA2251872A71500701F0C20800000006A734700000AA2251972BF15007016734800000AA2251A72D31500701E734800000AA2251B72ED15007016734800000AA2251C720316007016734800000AA2251D721B1600701E734800000AA2251E72291600701F0C156A734700000AA2734900000A13387E2A00000A133911332C23723716007011338C26000001282C00000A13391139283000000A1131281D00000A13391138161114252D06267E2A00000A6F4A00000A1138171115252D06267E2A00000A6F4A00000A1138181116252D06267E2A00000A6F4A00000A1138191134123A284B00000A2D04166A2B02113A6F4C00000A11381A1135123B284D00000A2D03162B02113B6F4E00000A11381B1136123C284B00000A2D04166A2B02113C6F4C00000A11381C1137123D284B00000A2D04166A2B02113D6F4C00000A11381D11336F4E00000A11381E11396F4A00000A282F00000A11386F4F00000A282F00000A11386F5000000A282F00000A6F5100000A1132282200000A2D16282F00000A72C81600701132282900000A6F3100000A11332C1772F616007011338C26000001282C00000A735200000A7ADE0C11302C0711306F5300000ADCDE1B1341725017007011416F5400000A282900000A1141735500000A7A2A00004134000002000000490D0000FB020000441000000C0000000000000000000000400D000012030000521000001B0000001700000146728C17007002728C170070281D00000A2A00001B3003009300000003000011022D02142A285600000A0A067E010000046F5700000A067E020000046F5800000A06176F5900000A06186F5A00000A735B00000A0B066F5C00000A0C070817735D00000A0D09735E00000A13041104026F5F00000ADE2011042C0711046F5300000ADC092C06096F5300000ADC082C06086F5300000ADC076F6000000A286100000A1305DE0A062C06066F5300000ADC11052A000134000002004D000A57000C00000000020045001E63000A0000000002003C00316D000A0000000002000B007B86000A000000001B300300A00000000400001102282200000A2C02142A02286200000A0A285600000A0B077E010000046F5700000A077E020000046F5800000A07176F5900000A07186F5A00000A06736300000A0C076F6400000A0D080916735D00000A13041104736500000A130511056F3B00000A1306DE3611052C0711056F5300000ADC11042C0711046F5300000ADC092C06096F5300000ADC082C06086F5300000ADC072C06076F5300000ADC11062A0140000002005C000B67000C00000000020053002073000C0000000002004900367F000A00000000020042004789000A00000000020017007C93000A00000000BE1F208D3C00000125D004000004286600000A80010000041F108D3C00000125D003000004286600000A80020000042A42534A4201000100000000000C00000076342E302E33303331390000000005006C00000098070000237E000004080000C40A000023537472696E677300000000C81200009017000023555300582A0000100000002347554944000000682A0000A803000023426C6F62000000000000000200000157950228090A000000FA013300160000010000003E00000006000000040000000700000048000000660000000F0000000200000004000000010000000200000001000000030000000200000001000000000098060100000000000600F304D60806006005D60806002904BF080F00F608000006003D0434070600D60434070600A204340706004705340706001305340706002C05340706006A04340706008504340706007E09DC060A00C10421080A00EC0505090A00540421080A000C0705090A004B00050906002300DC060E007907BF080E005A09BF080A000002210806005E07DC0606000E04D6080600D208910A0600C60649010600FB06910A0600B906910A0600090849010600A707490106001903DC0606003806DC0606007C0ADC0606005607DC0606006807DC0606005A0649010600A207DC0606005700DC060E00640A21090A00370A21080A00070321080600BA09DC060600B407490106005506DC060E004F0621090E00460721090E008A0721090E00C20321090A00960121080A000F038A010600E200DC060600B902DC060600E306910A06008302910A06006602910A0600CC06490106007202910A0600160849010600ED09DC0606009205DC0606004B09D6080600C502DC060000000005010000000001000100810110005301E70735000100010081011000CE07E707350001000500000100000E01000035000300080015010000E80000007D0005000800150100002E0000007D000500080031008A0A820231006A01820233015D00860233019E008A02502000000000960031068E02010074200000000096004D03950202003821000000009100730695022400E8310000000093000100DD024600FC31000000009600D109DD024700D032000000009600C609DD024800BC330000000091189808E2024900000001002D0A000001005608000002002303000003008E03000004003C08000005003F0100000600BF0700000700B10100000800F30700000900640300000A00CA0300000B00F50900000C00AE0A00000D00700100000E00A10200000F00380300001000A80300001100490800001200C10100001300FE0700001400790300001500D903000016007D0100001700AD02000018005D0200001900AE0500001A00F90100001B00200700001C008E0200001D00EF0100001E00AB0100001F00D80200002000490600002100E803000022008F0600000100560800000200230300000300FF05000004003C08000005003F0100000600BF0700000700B10100000800F307000009000E0200000A00CA0300000B00F50900000C00AE0A00000D00700100000E00A10200000F00380300001000130600001100490800001200C10100001300FE07000014001D0200001500D903000016007D0100001700AD02000018005D0200001900AE0500001A00F90100001B00200700001C008E0200001D00EF0100001E00AB0100001F00D80200002000490600002100E803000022008F06000001008B06000001002D0A00000100DA07090092080100110092080600190092080A00290092081000310092081000390092081000410092081000490092081000510092081000590092081000610092081000710092080600810092080600C100920806007900AE0615007900B4061900790097051D00790092081000790091092800790085092E000101F6061D000101A9091D008900AE0615008900970515009100AE061500910097058B000C00920895000901B8059B0001017009A90011019208100001013402B00001011B07B50001017009BC000101B40AB00001011A09C2000C00A105150001016A06C70001016A06C20021019007CF002901F6051D0001017009D2000101BC0AD8000C009705DB0001017709E00001011A09C70039012C02A9004101FE02E6005101F202EC004901EA011000A10092080600A100E5021000A10062091000A1007E05F000A100120AF000A1007808F000A100510AF000A900E709F500A900FF09FC005901D1011D00A9006608FC00A9009D090600A90047028B0001015F068B0061011707010101013F06070101013F060D0139014F061201690140091A017101D3062001810197051D00890192082701890192083001B10092083801B100270640019901F8034601B100DF004D013101F8035301B10054005A014901DC0960014901420A60014901DB010600B90092081000A101F0030600B90095021D00B90092086601C90001047B01A901820A8001A90163018001A90154028601A901C0058D01D10092080600A901AF089401E10092089901E9009208A501D10108041000D1007A0AAC01D901DD05B101D901CC05C701D10092088001A9019F089401F1009208A501E9016A0ACD0120006300A0032E000B00E6022E001300EF022E001B000E032E00230017032E002B0028032E00330056032E003B005C032E0043007C032E004B005C032E00530056032E005B00930340006B00A00380007300A00383007300A00301001000000005000100200000000600210034006D01B7018F00D86200000300E8620000040004800000000002000200000001000000E0012D010000040000000000000000000000D701A20100000000040000000000000000000000D7018A0100000000040000000000000000000000D701DC060000000005000400060004003900A5000000003C52756E466173745472616E73666572496E7465726E616C3E675F5F517C325F30004E756C6C61626C656031005F5F5374617469634172726179496E69745479706553697A653D33320053716C496E74333200536574496E7433320030354145344342453746383731373632353633433643363833333034313330444538313839374632343835313146343731423234413943433536303831463033004232363132444333343241453031374341344339413441443431313732463238443333304532433035343036343935443042393843323933343633333344333400536574496E743634005F5F5374617469634172726179496E69745479706553697A653D3136003C4D6F64756C653E003C50726976617465496D706C656D656E746174696F6E44657461696C733E004661737457726170706572735F5453514C00736F7572636544534E0053797374656D2E494F00466173745472616E73666572434C52007365745F495600416573495600736F75726365536368656D6100746172676574536368656D610053797374656D2E446174610053716C4D65746144617461006D73636F726C69620072756E4964006973536F7572636554727573746564006973546172676574547275737465640052656164546F456E640053656E64526573756C7473456E640053656E64006D61704D6574686F64006D6574686F640053716C446174615265636F726400736F7572636550617373776F72640074617267657450617373776F7264005265706C6163650049734E756C6C4F7257686974655370616365006765745F45786974436F6465007365745F4D6F6465006C6F61644D6F64650050616464696E674D6F64650043727970746F53747265616D4D6F6465004369706865724D6F646500646567726565006765745F4D65737361676500736F757263655461626C65007461726765745461626C650049446973706F7361626C650052756E74696D654669656C6448616E646C650073657474696E677346696C65007365745F46696C654E616D65006765745F4E65774C696E65006765745F506970650053716C506970650053716C4462547970650056616C75655479706500736F75726365436F6E6E656374696F6E5479706500746172676574436F6E6E656374696F6E547970650052756E466173745472616E736665725F53656375726500736F7572636550617373776F72645365637572650074617267657450617373776F726453656375726500736F75726365436F6E6E656374537472696E6753656375726500746172676574436F6E6E656374537472696E67536563757265004361707475726500736F757263654461746162617365007461726765744461746162617365006C6963656E736500446973706F73650054727950617273650043726561746500577269746500436F6D70696C657247656E6572617465644174747269627574650044656275676761626C6541747472696275746500417373656D626C795469746C654174747269627574650053716C50726F63656475726541747472696275746500417373656D626C7954726164656D61726B41747472696275746500417373656D626C7946696C6556657273696F6E41747472696275746500417373656D626C79436F6E66696775726174696F6E4174747269627574650053716C46756E6374696F6E41747472696275746500417373656D626C794465736372697074696F6E41747472696275746500436F6D70696C6174696F6E52656C61786174696F6E7341747472696275746500417373656D626C7950726F6475637441747472696275746500417373656D626C79436F7079726967687441747472696275746500417373656D626C79436F6D70616E794174747269627574650052756E74696D65436F6D7061746962696C697479417474726962757465007365745F5573655368656C6C457865637574650042797465006765745F56616C7565006765745F48617356616C756500626174636853697A6500496E6465784F66007365745F50616464696E670046726F6D426173653634537472696E6700546F426173653634537472696E670053716C537472696E6700546F537472696E6700736F75726365436F6E6E656374537472696E6700746172676574436F6E6E656374537472696E6700536574537472696E6700456E6372797074537472696E6700537562737472696E67006465627567004D61746368004D6174680050617468006765745F4C656E67746800456E6473576974680052756E466173745472616E73666572496E7465726E616C0076616C006C6F676C6576656C004661737457726170706572735F5453514C2E646C6C006765745F49734E756C6C0043727970746F53747265616D004D656D6F727953747265616D006765745F4974656D0053797374656D0053796D6D6574726963416C676F726974686D005472696D004943727970746F5472616E73666F726D0053716C426F6F6C65616E004D696E004A6F696E00646973747269627574654B6579436F6C756D6E0053797374656D2E5265666C656374696F6E0047726F7570436F6C6C656374696F6E00417267756D656E74457863657074696F6E00537472696E67436F6D70617269736F6E0050726F636573735374617274496E666F0047726F7570004469726563746F7279536570617261746F72436861720053747265616D526561646572005465787452656164657200736F7572636550726F7669646572004B657950726F76696465720062617365363443697068657200466173745772617070657200736F757263655573657200746172676574557365720053747265616D5772697465720054657874577269746572004D6963726F736F66742E53716C5365727665722E53657276657200736F757263655365727665720074617267657453657276657200666173745472616E73666572446972006765745F5374616E646172644572726F72007365745F52656469726563745374616E646172644572726F72002E63746F72002E6363746F7200437265617465446563727970746F7200437265617465456E63727970746F720053797374656D2E446961676E6F7374696373004165730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300446562756767696E674D6F6465730053797374656D2E446174612E53716C547970657300457175616C730053797374656D2E546578742E526567756C617245787072657373696F6E73006765745F47726F7570730052756E74696D6548656C706572730050726F63657373007365745F417267756D656E747300436F6E63617400466F726D6174004F626A656374006F705F496D706C69636974006F705F4578706C696369740057616974466F724578697400546F4C6F776572496E76617269616E7400456E7669726F6E6D656E74004165734465637279707400416573456E63727970740053656E64526573756C7473537461727400436F6E766572740066696C65496E707574006765745F5374616E646172644F7574707574007365745F52656469726563745374616E646172644F757470757400706C61696E546578740053716C436F6E746578740053656E64526573756C7473526F77007365745F4372656174654E6F57696E646F7700526567657800496E697469616C697A65417272617900546F4172726179007365745F4B6579004165734B65790053797374656D2E53656375726974792E43727970746F6772617068790071756572790049734E756C6C4F72456D707479000000001769006E0066006F0072006D006100740069006F006E00000B6500720072006F007200000F7700610072006E0069006E006700000B64006500620075006700002749006E00760061006C006900640020006C006F0067006C006500760065006C003A00200027000180BB27002E002000550073006500200027006500720072006F00720027002C00200027007700610072006E0069006E00670027002C002000270069006E0066006F0072006D006100740069006F006E0027002C0020006F007200200027006400650062007500670027002E0020005700410052004E0049004E0047002000740068006500200070006100720061006D006500740065007200200069007300200043006100730065002000530065006E007300690074006900760065000180A966006100730074005400720061006E00730066006500720044006900720020006D007500730074002000620065002000700072006F0076006900640065006400200028006400690072006500630074006F0072007900200063006F006E007400610069006E0069006E0067002000740068006500200046006100730074005400720061006E0073006600650072002000650078006500630075007400610062006C00650029002E00001563006C00690063006B0068006F00750073006500000D6400750063006B006400620000196400750063006B0064006200730074007200650061006D000009680061006E006100000B6D007300730071006C00000B6D007900730071006C00000B6E007A00730071006C0000096F00640062006300000B6F006C00650064006200000D6F00720061006F0064007000000D7000670063006F0070007900000B70006700730071006C00001174006500720061006400610074006100003F49006E00760061006C0069006400200053006F00750072006300650043006F006E006E0065006300740069006F006E0054007900700065003A0020002700012D27002E00200050006F0073007300690062006C0065002000760061006C00750065002000610072006500200001052C00200000032E00001D63006C00690063006B0068006F00750073006500620075006C006B000011680061006E006100620075006C006B00000D6D007300620075006C006B0000136D007900730071006C00620075006C006B00000D6E007A00620075006C006B00000F6F0072006100620075006C006B0000136F0072006100640069007200650063007400003F49006E00760061006C0069006400200054006100720067006500740043006F006E006E0065006300740069006F006E0054007900700065003A00200027000180A95700680065006E00200073006F00750072006300650043006F006E006E0065006300740053007400720069006E0067002000690073002000700072006F00760069006400650064002C00200064006F0020006E006F007400200073007500700070006C00790020007300650072007600650072002F00440053004E002F00630072006500640065006E007400690061006C0073002F00640061007400610062006100730065002E0000809B4D007500730074002000700072006F0076006900640065002000650069007400680065007200200073006F00750072006300650053006500720076006500720020006F007200200073006F007500720063006500440053004E00200069006600200073006F00750072006300650043006F006E006E0065006300740053007400720069006E00670020006900730020004E0055004C004C002E00007F4D007500730074002000700072006F007600690064006500200073006F0075007200630065004400610074006100620061007300650020007700680065006E0020006E006F00740020007500730069006E006700200073006F00750072006300650043006F006E006E0065006300740053007400720069006E0067002E000080854D007500730074002000700072006F007600690064006500200073006F0075007200630065005500730065007200200061006E006400200073006F007500720063006500500061007300730077006F007200640020007700680065006E00200073006F007500720063006500540072007500730074006500640020003D00200030002E000080A959006F00750020006D00750073007400200073007500700070006C00790020006100740020006C00650061007300740020006F006E00650020006F0066002000660069006C00650049006E007000750074002C002000710075006500720079002C0020006F0072002000280073006F00750072006300650053006300680065006D006100200041004E004400200073006F0075007200630065005400610062006C00650029002E00005D59006F00750020006D00750073007400200073007500700070006C00790020006F006E006C00790020006F006E00650020006F0066002000660069006C00650049006E0070007500740020006F0072002000710075006500720079000080A15700680065006E00200074006100720067006500740043006F006E006E0065006300740053007400720069006E0067002000690073002000700072006F00760069006400650064002C00200064006F0020006E006F007400200073007500700070006C00790020007300650072007600650072002F00630072006500640065006E007400690061006C0073002F00640061007400610062006100730065002E0000734D007500730074002000700072006F0076006900640065002000740061007200670065007400530065007200760065007200200069006600200074006100720067006500740043006F006E006E0065006300740053007400720069006E00670020006900730020004E0055004C004C002E0000774D007500730074002000700072006F007600690064006500200074006100720067006500740044006100740061006200610073006500200069006600200074006100720067006500740043006F006E006E0065006300740053007400720069006E00670020006900730020004E0055004C004C002E000080854D007500730074002000700072006F00760069006400650020007400610072006700650074005500730065007200200061006E0064002000740061007200670065007400500061007300730077006F007200640020007700680065006E002000740061007200670065007400540072007500730074006500640020003D00200030002E0000554D007500730074002000700072006F007600690064006500200074006100720067006500740053006300680065006D006100200061006E00640020007400610072006700650074005400610062006C0065002E0000094E006F006E006500000D520061006E0064006F006D0000154400610074006100440072006900760065006E00000F520061006E006700650049006400000B4E00740069006C00650000094300740069006400000B52006F0077006900640000174E005A00440061007400610053006C00690063006500002349006E00760061006C006900640020006D006500740068006F0064003A002000270001810927002E002000750073006500200027004E006F006E00650027002C0020002700520061006E0064006F006D0027002C00200027004400610074006100440072006900760065006E0027002C0020002700520061006E00670065004900640027002C00200027004E00740069006C00650027002C00200027004E005A00440061007400610053006C0069006300650027002C00200027004300740069006400270020006F0072002000270052006F0077006900640027002E0020005700410052004E0049004E0047002000740068006500200070006100720061006D006500740065007200200069007300200043006100730065002000530065006E0073006900740069007600650001215700680065006E0020006D006500740068006F00640020006900730020002700015527002C00200079006F00750020006D007500730074002000700072006F00760069006400650020002D002D0064006900730074007200690062007500740065004B006500790043006F006C0075006D006E002E000180855700680065006E002000730070006500630069006600790069006E0067002000610020006D006500740068006F00640020006F00740068006500720020007400680061006E0020004E006F006E0065002C00200079006F00750020006D007500730074002000700072006F00760069006400650020006400650067007200650065002E00000D41007000700065006E00640000115400720075006E006300610074006500002749006E00760061006C006900640020006C006F00610064006D006F00640065003A002000270001808F27002E0020005500730065002000270041007000700065006E006400270020006F007200200027005400720075006E00630061007400650027002E00200020005700410052004E0049004E0047002000740068006500200070006100720061006D006500740065007200200069007300200043006100730065002000530065006E00730069007400690076006500011150006F0073006900740069006F006E0000094E0061006D006500002949006E00760061006C006900640020006D00610070004D006500740068006F0064003A002000270001808B27002E0020007500730065002000270050006F0073006900740069006F006E00270020006F007200200027004E0061006D00650027002E00200020005700410052004E0049004E0047002000740068006500200070006100720061006D006500740065007200200069007300200043006100730065002000530065006E00730069007400690076006500012146006100730074005400720061006E0073006600650072002E00650078006500001966006100730074007400720061006E00730066006500720000035C0000032F00003120002D002D0073006F00750072006300650063006F006E006E0065006300740069006F006E0074007900700065002000012F20002D002D0073006F00750072006300650063006F006E006E0065006300740073007400720069006E0067002000012120002D002D0073006F0075007200630065007300650072007600650072002000012520002D002D0073006F007500720063006500700072006F00760069006400650072002000011B20002D002D0073006F007500720063006500640073006E002000012120002D002D0073006F0075007200630065007400720075007300740065006400011D20002D002D0073006F00750072006300650075007300650072002000012520002D002D0073006F007500720063006500700061007300730077006F00720064002000012520002D002D0073006F007500720063006500640061007400610062006100730065002000011B20002D002D00660069006C00650069006E007000750074002000011320002D002D00710075006500720079002000012120002D002D0073006F00750072006300650073006300680065006D0061002000011F20002D002D0073006F0075007200630065007400610062006C0065002000013120002D002D0074006100720067006500740063006F006E006E0065006300740069006F006E0074007900700065002000012F20002D002D0074006100720067006500740063006F006E006E0065006300740073007400720069006E0067002000012120002D002D007400610072006700650074007300650072007600650072002000012120002D002D007400610072006700650074007400720075007300740065006400011D20002D002D0074006100720067006500740075007300650072002000012520002D002D00740061007200670065007400700061007300730077006F00720064002000012520002D002D00740061007200670065007400640061007400610062006100730065002000012120002D002D0074006100720067006500740073006300680065006D0061002000011F20002D002D007400610072006700650074007400610062006C0065002000011920002D002D006C006F00610064006D006F00640065002000012120002D002D0062006100740063006800730069007A00650020007B0030007D00011520002D002D006D006500740068006F0064002000010D720061006E0064006F006D0000156400610074006100640072006900760065006E00000F720061006E006700650069006400000B6E00740069006C006500002F20002D002D0064006900730074007200690062007500740065004B006500790043006F006C0075006D006E002000011B20002D002D0064006500670072006500650020007B0030007D00011B20002D002D006D00610070006D006500740068006F0064002000011320002D002D00720075006E00690064002000012120002D002D00730065007400740069006E0067007300660069006C0065002000011720002D002D006C006900630065006E00730065002000011920002D002D006C006F0067006C006500760065006C00200001352D002D0073006F007500720063006500700061007300730077006F00720064005C0073002B0022005B005E0022005D002A00220001372D002D0073006F007500720063006500700061007300730077006F0072006400200022003C00680069006400640065006E003E00220001352D002D00740061007200670065007400700061007300730077006F00720064005C0073002B0022005B005E0022005D002A00220001372D002D00740061007200670065007400700061007300730077006F0072006400200022003C00680069006400640065006E003E002200013F2D002D0073006F00750072006300650063006F006E006E0065006300740073007400720069006E0067005C0073002B0022005B005E0022005D002A00220001412D002D0073006F00750072006300650063006F006E006E0065006300740073007400720069006E006700200022003C00680069006400640065006E003E002200013F2D002D0074006100720067006500740063006F006E006E0065006300740073007400720069006E0067005C0073002B0022005B005E0022005D002A00220001412D002D0074006100720067006500740063006F006E006E0065006300740073007400720069006E006700200022003C00680069006400640065006E003E002200012B46006100730074005400720061006E007300660065007200200043006F006D006D0061006E006400200000032000002D54006F00740061006C00200072006F00770073005C0073002A003A005C0073002A0028005C0064002B002900003354006F00740061006C00200063006F006C0075006D006E0073005C0073002A003A005C0073002A0028005C0064002B002900002F54006F00740061006C002000630065006C006C0073005C0073002A003A005C0073002A0028005C0064002B002900003145006C00610070007300650064005C0073002A003D005C0073002A0028005C0064002B0029005C0073002A006D007300001D74006100720067006500740064006100740061006200610073006500001974006100720067006500740053006300680065006D00610000177400610072006700650074005400610062006C006500001354006F00740061006C0052006F0077007300001954006F00740061006C0043006F006C0075006D006E007300001554006F00740061006C00430065006C006C007300001754006F00740061006C00540069006D0065004D007300000D530074006100740075007300000D53007400640045007200720000808F46006100730074005400720061006E0073006600650072002000700072006F00630065007300730020006600610069006C00650064002000770069007400680020006500780069007400200063006F006400650020007B0030007D002E0020005300650065002000730074006400650072007200200066006F0072002000640065007400610069006C0073002E00002D46006100730074005400720061006E00730066006500720020007300740064006500720072003A000D000A00005946006100730074005400720061006E0073006600650072002000700072006F0063006500730073002000720065007400750072006E006500640020006500780069007400200063006F006400650020007B0030007D002E00003B4500720072006F007200200069006E0076006F006B0069006E006700200046006100730074005400720061006E0073006600650072003A002000000322000077144D9FB1D4AA4AA1CC6E071A6D2BE400042001010803200001052001011111042001010E032000020306113D0320000E0607040E0E0E0E0500010E113D050001113D0E5607420E0E0E0E0E0E020E0E0E0E0E0E0E0E0E0E020E0E0E0E0E0E15114D01080E0E15114D01080E0E0E020E0E1D0E1D0E02080202020E0E0E125115114D01080E0312550E0E080E0E0E0E12590E0A080A0A08080E125D032000080515114D010805200101130009100102081D1E001E00030A010E0600030E0E0E0E040001020E0600020E0E1D0E0500010E1D0E042001020E072002020E11808D0206030500020E0E0E02060E04200013000500020E0E1C0500001280A50300000E04200101020600011255125104200012790500020808080520020E08080420010E080700021280B50E0E0520001280B90620011280BD08082003010E1180C90A072002010E1180C9072001011D1280C505200201080E060002020E100A05200201080A060002020E1008052002010808052001011259062002010E125D0D070612651269126D127112750E0400001265052001011D05062001011180D9062001011180DD042000126D0B2003011280E1126D1180E5062001011280E10420001D050500010E1D050F07071D0512651269126D127112790E0500011D050E090002011280851180F908B77A5C561934E08980A0002400000480000094000000060200000024000052534131000400000100010041AB0C528E5478F2CB94BEC28F84956BAD3F2A208D6CDC21EBFA4BED2B4FACBE543F6F667C69D1597951DE3A1DA78303C687C5F71FFD6A67C3FE52C51BD0395F4163CE187D2807132385C94243BEF17286AA36DD4E52B5B16107D637421417CD8E5DAE1DD0ABB5264EC8DE08015C0D37E46AA6F56707DD23991FC1596328A5D003061D050306111403061118060001113D113D47002201113D113D113D113D113D113D1145113D113D113D113D113D113D113D113D113D113D1145113D113D113D113D113D113D1149113D113D1149113D113D113D1145113D113D0400010E0E030000010801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F7773010801000200000000001001000B466173745772617070657200002D010028434C52205772617070657220666F7220466173745472616E7366657220616E64204661737442435000000501000000001F01001A417263686974656374757265202620506572666F726D616E63650000160100114661737457726170706572735F5453514C00000C010007302E322E322E30000004010000000000003F822C7ADBA3A8882411F02799BE754357F837259CEEFC399D7D695F723BAD51BC44EA6AC0CE8A943400131E30818EAB727D379A9A04C6327144CDEA2FB6F9116BDE6AA19E2E5C909D4C1B657EC94D9CA8A8258C956990A6FB49FD80CE01529EDA6402B4C43D3DB9577239D0EAAC17A789F5141C7145D854AC25C6709F55099EA46200000000000000000000BE620000002000000000000000000000000000000000000000000000B0620000000000000000000000005F436F72446C6C4D61696E006D73636F7265652E646C6C0000000000FF2500200010000000001122AA77559910016633450F3A2BCCEE013358A73B992DFA6211D5E78F2C990AF26844FA4892BE65107ACAAC9EDE7F0C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100100000001800008000000000000000000000000000000100010000003000008000000000000000000000000000000100000000004800000058800000E80300000000000000000000E80334000000560053005F00560045005200530049004F004E005F0049004E0046004F0000000000BD04EFFE00000100020000000000020002000000000002003F000000000000000400000002000000000000000000000000000000440000000100560061007200460069006C00650049006E0066006F00000000002400040000005400720061006E0073006C006100740069006F006E00000000000000B00448030000010053007400720069006E006700460069006C00650049006E0066006F0000002403000001003000300030003000300034006200300000006A002900010043006F006D006D0065006E0074007300000043004C00520020005700720061007000700065007200200066006F007200200046006100730074005400720061006E007300660065007200200061006E006400200046006100730074004200430050000000000056001B00010043006F006D00700061006E0079004E0061006D0065000000000041007200630068006900740065006300740075007200650020002600200050006500720066006F0072006D0061006E00630065000000000040000C000100460069006C0065004400650073006300720069007000740069006F006E0000000000460061007300740057007200610070007000650072000000300008000100460069006C006500560065007200730069006F006E000000000030002E0032002E0032002E00300000004C001600010049006E007400650072006E0061006C004E0061006D00650000004600610073007400570072006100700070006500720073005F005400530051004C002E0064006C006C0000005A001B0001004C006500670061006C0043006F007000790072006900670068007400000041007200630068006900740065006300740075007200650020002600200050006500720066006F0072006D0061006E0063006500000000002A00010001004C006500670061006C00540072006100640065006D00610072006B00730000000000000000005400160001004F0072006900670069006E0061006C00460069006C0065006E0061006D00650000004600610073007400570072006100700070006500720073005F005400530051004C002E0064006C006C000000440012000100500072006F0064007500630074004E0061006D006500000000004600610073007400570072006100700070006500720073005F005400530051004C000000340008000100500072006F006400750063007400560065007200730069006F006E00000030002E0032002E0032002E003000000038000800010041007300730065006D0062006C0079002000560065007200730069006F006E00000030002E0032002E0032002E003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000C000000D03200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +WITH PERMISSION_SET = UNSAFE +GO +/****** Object: UserDefinedFunction [dbo].[EncryptString] Script Date: 2025-10-13 23:19:40 ******/ +SET ANSI_NULLS OFF +GO +SET QUOTED_IDENTIFIER OFF +GO +CREATE FUNCTION [dbo].[EncryptString](@plainText [nvarchar](max)) +RETURNS [nvarchar](max) WITH EXECUTE AS CALLER +AS +EXTERNAL NAME [FastWrappers_TSQL].[FastWrapper.FastTransferCLR].[EncryptString] +GO +/****** Object: StoredProcedure [dbo].[RunFastTransfer_Secure] Script Date: 2025-10-13 23:19:40 ******/ +SET ANSI_NULLS OFF +GO +SET QUOTED_IDENTIFIER OFF +GO +CREATE PROCEDURE [dbo].[RunFastTransfer_Secure] + @fastTransferDir [nvarchar](max), + @sourceConnectionType [nvarchar](max), + @sourceConnectStringSecure [nvarchar](max), + @sourceServer [nvarchar](max), + @sourceDSN [nvarchar](max), + @sourceProvider [nvarchar](max), + @isSourceTrusted [bit], + @sourceUser [nvarchar](max), + @sourcePasswordSecure [nvarchar](max), + @sourceDatabase [nvarchar](max), + @fileInput [nvarchar](max), + @query [nvarchar](max), + @sourceSchema [nvarchar](max), + @sourceTable [nvarchar](max), + @targetConnectionType [nvarchar](max), + @targetConnectStringSecure [nvarchar](max), + @targetServer [nvarchar](max), + @isTargetTrusted [bit], + @targetUser [nvarchar](max), + @targetPasswordSecure [nvarchar](max), + @targetDatabase [nvarchar](max), + @targetSchema [nvarchar](max), + @targetTable [nvarchar](max), + @loadMode [nvarchar](max), + @batchSize [int], + @method [nvarchar](max), + @distributeKeyColumn [nvarchar](max), + @degree [int], + @mapMethod [nvarchar](max), + @runId [nvarchar](max), + @settingsFile [nvarchar](max), + @debug [bit], + @license [nvarchar](max), + @loglevel [nvarchar](max) +WITH EXECUTE AS CALLER +AS +EXTERNAL NAME [FastWrappers_TSQL].[FastWrapper.FastTransferCLR].[RunFastTransfer_Secure] +GO +/****** Object: StoredProcedure [dbo].[xp_RunFastTransfer_secure] Script Date: 2025-10-13 23:19:40 ******/ +SET ANSI_NULLS OFF +GO +SET QUOTED_IDENTIFIER OFF +GO +CREATE PROCEDURE [dbo].[xp_RunFastTransfer_secure] + @fastTransferDir [nvarchar](max), + @sourceConnectionType [nvarchar](30), + @sourceConnectStringSecure [nvarchar](4000) = N'', + @sourceServer [nvarchar](255), + @sourceDSN [nvarchar](255) = N'', + @sourceProvider [nvarchar](1000) = N'', + @isSourceTrusted [bit] = False, + @sourceUser [nvarchar](1000) = N'', + @sourcePasswordSecure [nvarchar](255) = N'', + @sourceDatabase [nvarchar](1000), + @fileInput [nvarchar](4000) = N'', + @query [nvarchar](4000) = N'', + @sourceSchema [nvarchar](255) = N'', + @sourceTable [nvarchar](255) = N'', + @targetConnectionType [nvarchar](30), + @targetConnectStringSecure [nvarchar](4000) = N'', + @targetServer [nvarchar](255), + @isTargetTrusted [bit] = False, + @targetUser [nvarchar](1000) = N'', + @targetPasswordSecure [nvarchar](255) = N'', + @targetDatabase [nvarchar](255), + @targetSchema [nvarchar](255), + @targetTable [nvarchar](255), + @loadMode [nvarchar](50), + @batchSize [int] = 1048576, + @method [nvarchar](50) = N'None', + @distributeKeyColumn [nvarchar](255) = N'', + @degree [int] = 4, + @mapmethod [nvarchar](50) = N'Position', + @runId [nvarchar](255) = N'', + @settingsFile [nvarchar](4000) = N'', + @debug [bit] = False, + @license [nvarchar](4000) = N'', + @loglevel [nvarchar](50) = N'information' +WITH EXECUTE AS CALLER +AS +EXTERNAL NAME [FastWrappers_TSQL].[FastWrapper.FastTransferCLR].[RunFastTransfer_Secure] +GO diff --git a/README.md b/README.md index 50a8fbf..b65177d 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,28 @@ As a reminder : - **FastTransfer** is a CLI that allow import from file or transfer data between databases using streaming and parallel mecanism for high performance - **FastBCP** is a CLI that allow to export data from databases to files (csv, parquet, json,bson and excel) using streaming and parallel mecanism for high performance +## Installation + +Download the latest release from the [Releases page](https://github.com/aetperf/FastWrappers-TSQL/releases). Each release provides 4 installation options: + +1. **FastWrappers-TSQL.dacpac** - Data-tier Application Package (recommended for Visual Studio / SQL Server Data Tools) +2. **FastWrappers-TSQL.bacpac** - Binary Application Package (for import/export between servers) +3. **FastWrappers-TSQL.bak** - SQL Server Backup file (compatible with SQL Server 2016+, restore using SSMS) +4. **FastWrappers-TSQL.sql** - Pure SQL Script (execute using sqlcmd or SSMS) + +## Creating a New Release + +To create a new release: + +1. Update the version number in [Properties/AssemblyInfo.cs](Properties/AssemblyInfo.cs) +2. Commit your changes +3. Create and push a new tag: + ```bash + git tag v0.3.3 + git push origin v0.3.3 + ``` +4. The GitHub Actions workflow will automatically build and create a release with all installation artifacts + Samples usage : ### Copy one table using 12 threads between two MSSQL instances From ab0a443c2a7a985d9c6f60f1e30996beded4285a Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 12:05:21 +0100 Subject: [PATCH 02/37] Enhance release workflow: add artifact verification, improve error handling, and streamline release file preparation --- .github/workflows/release.yml | 99 +++++++++++++++++++++++++++++++---- 1 file changed, 89 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2cdf4c4..a25cf8c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,7 +23,28 @@ jobs: run: nuget restore FastWrappers-TSQL.sln - name: Build SQL Project - run: msbuild FastWrappers_TSQL.sqlproj /p:Configuration=Release /p:Platform="Any CPU" + run: msbuild FastWrappers_TSQL.sqlproj /p:Configuration=Release /p:Platform="Any CPU" /t:Build,Package + + - name: Verify Build Artifacts + shell: powershell + run: | + Write-Host "Checking for build output..." + if (Test-Path "bin") { + Get-ChildItem -Path "bin" -Recurse -File | Format-Table FullName, Length + } else { + Write-Host "bin folder does not exist!" + } + + # Check for DACPAC + $dacpacPath = "bin\Release\FastWrappers_TSQL.dacpac" + if (Test-Path $dacpacPath) { + Write-Host "✓ DACPAC found at: $dacpacPath" + } else { + Write-Host "✗ DACPAC not found at: $dacpacPath" + Write-Host "Looking for .dacpac files..." + Get-ChildItem -Path . -Filter "*.dacpac" -Recurse -ErrorAction SilentlyContinue | Format-Table FullName + exit 1 + } - name: Setup SQL Server (LocalDB) shell: powershell @@ -44,12 +65,26 @@ jobs: $dacpacPath = "bin\Release\FastWrappers_TSQL.dacpac" $bacpacPath = "bin\Release\FastWrappers-TSQL.bacpac" $bakPath = "bin\Release\FastWrappers-TSQL.bak" + $generatedSqlPath = "bin\Release\FastWrappers-TSQL.sql" + + # Ensure output directory exists + if (!(Test-Path "bin\Release")) { + Write-Host "Creating bin\Release directory..." + New-Item -Path "bin\Release" -ItemType Directory -Force | Out-Null + } + + # Verify DACPAC exists + if (!(Test-Path $dacpacPath)) { + Write-Error "DACPAC not found at: $dacpacPath" + exit 1 + } # Download SqlPackage if needed if (!(Test-Path "SqlPackage\SqlPackage.exe")) { Write-Host "Downloading SqlPackage..." Invoke-WebRequest -Uri "https://aka.ms/sqlpackage-windows" -OutFile "SqlPackage.zip" - Expand-Archive -Path "SqlPackage.zip" -DestinationPath "SqlPackage" + Expand-Archive -Path "SqlPackage.zip" -DestinationPath "SqlPackage" -Force + Remove-Item "SqlPackage.zip" } $sqlPackage = "SqlPackage\SqlPackage.exe" @@ -58,6 +93,11 @@ jobs: Write-Host "Deploying DACPAC to create database..." & $sqlPackage /Action:Publish /SourceFile:$dacpacPath /TargetServerName:$serverInstance /TargetDatabaseName:$dbName /p:IncludeCompositeObjects=True + if ($LASTEXITCODE -ne 0) { + Write-Error "Failed to deploy DACPAC" + exit 1 + } + # Wait for deployment to complete Start-Sleep -Seconds 5 @@ -65,26 +105,68 @@ jobs: Write-Host "Exporting to BACPAC..." & $sqlPackage /Action:Export /SourceServerName:$serverInstance /SourceDatabaseName:$dbName /TargetFile:$bacpacPath + if ($LASTEXITCODE -ne 0) { + Write-Warning "Failed to create BACPAC, continuing..." + } + # Create .bak file with compatibility level for SQL Server 2016 Write-Host "Creating SQL Server 2016 compatible backup..." - sqlcmd -S $serverInstance -Q "ALTER DATABASE [$dbName] SET COMPATIBILITY_LEVEL = 130; BACKUP DATABASE [$dbName] TO DISK = N'$PWD\$bakPath' WITH COMPRESSION, STATS = 10" + $bakFullPath = Join-Path $PWD $bakPath + sqlcmd -S $serverInstance -Q "ALTER DATABASE [$dbName] SET COMPATIBILITY_LEVEL = 130; BACKUP DATABASE [$dbName] TO DISK = N'$bakFullPath' WITH COMPRESSION, STATS = 10" + + if ($LASTEXITCODE -ne 0) { + Write-Warning "Failed to create BAK file, continuing..." + } # Generate SQL script from DACPAC (includes the compiled binary) Write-Host "Generating SQL script from DACPAC..." - $generatedSqlPath = "bin\Release\FastWrappers-TSQL.sql" & $sqlPackage /Action:Script /SourceFile:$dacpacPath /OutputPath:$generatedSqlPath /p:IncludeCompositeObjects=True + if ($LASTEXITCODE -ne 0) { + Write-Warning "Failed to generate SQL script, continuing..." + } + # Copy DACPAC with proper name Write-Host "Copying DACPAC with release name..." - Copy-Item $dacpacPath "bin\Release\FastWrappers-TSQL.dacpac" + Copy-Item $dacpacPath "bin\Release\FastWrappers-TSQL.dacpac" -Force + + # List all created artifacts + Write-Host "`nCreated artifacts:" + Get-ChildItem -Path "bin\Release" -File | Format-Table Name, Length - Write-Host "All artifacts created successfully!" + Write-Host "All artifacts processing completed!" - name: Get version from tag id: get_version shell: bash run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT + - name: Prepare Release Files + shell: powershell + run: | + # Create a release directory with all available artifacts + New-Item -Path "release" -ItemType Directory -Force | Out-Null + + # Copy available files + $files = @( + @{Source="bin\Release\FastWrappers-TSQL.dacpac"; Name="FastWrappers-TSQL.dacpac"}, + @{Source="bin\Release\FastWrappers-TSQL.bacpac"; Name="FastWrappers-TSQL.bacpac"}, + @{Source="bin\Release\FastWrappers-TSQL.bak"; Name="FastWrappers-TSQL.bak"}, + @{Source="bin\Release\FastWrappers-TSQL.sql"; Name="FastWrappers-TSQL.sql"} + ) + + foreach ($file in $files) { + if (Test-Path $file.Source) { + Copy-Item $file.Source "release\$($file.Name)" -Force + Write-Host "✓ Copied $($file.Name)" + } else { + Write-Warning "✗ $($file.Name) not found, skipping" + } + } + + Write-Host "`nRelease files:" + Get-ChildItem -Path "release" | Format-Table Name, Length + - name: Create Release id: create_release uses: softprops/action-gh-release@v1 @@ -106,10 +188,7 @@ jobs: See [README.md](https://github.com/${{ github.repository }}/blob/main/README.md) for usage examples. files: | - bin/Release/FastWrappers-TSQL.dacpac - bin/Release/FastWrappers-TSQL.bacpac - bin/Release/FastWrappers-TSQL.bak - bin/Release/FastWrappers-TSQL.sql + release/* draft: false prerelease: false env: From ae18d00966eb5f5f241f3a7d6353c356e66ac765 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 12:08:57 +0100 Subject: [PATCH 03/37] Fix release workflow: update DACPAC path, adjust output directory, and refine build steps --- .github/workflows/release.yml | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a25cf8c..ce670d7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,7 +23,7 @@ jobs: run: nuget restore FastWrappers-TSQL.sln - name: Build SQL Project - run: msbuild FastWrappers_TSQL.sqlproj /p:Configuration=Release /p:Platform="Any CPU" /t:Build,Package + run: msbuild FastWrappers_TSQL.sqlproj /p:Configuration=Release /p:Platform="Any CPU" /t:Build - name: Verify Build Artifacts shell: powershell @@ -35,8 +35,8 @@ jobs: Write-Host "bin folder does not exist!" } - # Check for DACPAC - $dacpacPath = "bin\Release\FastWrappers_TSQL.dacpac" + # Check for DACPAC in bin\Output (SQL Projects output here) + $dacpacPath = "bin\Output\FastWrappers_TSQL.dacpac" if (Test-Path $dacpacPath) { Write-Host "✓ DACPAC found at: $dacpacPath" } else { @@ -62,15 +62,16 @@ jobs: # Variables $serverInstance = "(localdb)\MSSQLLocalDB" $dbName = "FastWrappers-TSQL" - $dacpacPath = "bin\Release\FastWrappers_TSQL.dacpac" - $bacpacPath = "bin\Release\FastWrappers-TSQL.bacpac" - $bakPath = "bin\Release\FastWrappers-TSQL.bak" - $generatedSqlPath = "bin\Release\FastWrappers-TSQL.sql" + $dacpacPath = "bin\Output\FastWrappers_TSQL.dacpac" + $outputDir = "bin\Release" + $bacpacPath = "$outputDir\FastWrappers-TSQL.bacpac" + $bakPath = "$outputDir\FastWrappers-TSQL.bak" + $generatedSqlPath = "$outputDir\FastWrappers-TSQL.sql" # Ensure output directory exists - if (!(Test-Path "bin\Release")) { - Write-Host "Creating bin\Release directory..." - New-Item -Path "bin\Release" -ItemType Directory -Force | Out-Null + if (!(Test-Path $outputDir)) { + Write-Host "Creating $outputDir directory..." + New-Item -Path $outputDir -ItemType Directory -Force | Out-Null } # Verify DACPAC exists @@ -128,11 +129,11 @@ jobs: # Copy DACPAC with proper name Write-Host "Copying DACPAC with release name..." - Copy-Item $dacpacPath "bin\Release\FastWrappers-TSQL.dacpac" -Force + Copy-Item $dacpacPath "$outputDir\FastWrappers-TSQL.dacpac" -Force # List all created artifacts Write-Host "`nCreated artifacts:" - Get-ChildItem -Path "bin\Release" -File | Format-Table Name, Length + Get-ChildItem -Path $outputDir -File | Format-Table Name, Length Write-Host "All artifacts processing completed!" From b4ac62da72a2ff725eb35610aef52748dc99d7d5 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 12:24:53 +0100 Subject: [PATCH 04/37] Refactor logging messages in release workflow for consistency --- .github/workflows/release.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ce670d7..3669e7d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -38,9 +38,9 @@ jobs: # Check for DACPAC in bin\Output (SQL Projects output here) $dacpacPath = "bin\Output\FastWrappers_TSQL.dacpac" if (Test-Path $dacpacPath) { - Write-Host "✓ DACPAC found at: $dacpacPath" + Write-Host "DACPAC found at: $dacpacPath" } else { - Write-Host "✗ DACPAC not found at: $dacpacPath" + Write-Host "DACPAC not found at: $dacpacPath" Write-Host "Looking for .dacpac files..." Get-ChildItem -Path . -Filter "*.dacpac" -Recurse -ErrorAction SilentlyContinue | Format-Table FullName exit 1 @@ -159,9 +159,9 @@ jobs: foreach ($file in $files) { if (Test-Path $file.Source) { Copy-Item $file.Source "release\$($file.Name)" -Force - Write-Host "✓ Copied $($file.Name)" + Write-Host "Copied $($file.Name)" } else { - Write-Warning "✗ $($file.Name) not found, skipping" + Write-Warning "$($file.Name) not found, skipping" } } From 4980769ff16068307674ca11ee7c456f65478090 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 12:30:27 +0100 Subject: [PATCH 05/37] Target SQL Server 2016 for maximum compatibility --- FastWrappers_TSQL.sqlproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FastWrappers_TSQL.sqlproj b/FastWrappers_TSQL.sqlproj index e78edfe..6445cda 100644 --- a/FastWrappers_TSQL.sqlproj +++ b/FastWrappers_TSQL.sqlproj @@ -7,7 +7,7 @@ 2.0 4.1 {4b096d13-154a-472c-9882-f281334958f9} - Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider + Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider Database @@ -36,7 +36,7 @@ 2.0.0.0 - bin\Release\ + bin\Output\ $(MSBuildProjectName).sql False none From 0277a00d7628389d9b59410c617e9ce2977cb3b6 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 13:02:03 +0100 Subject: [PATCH 06/37] Fix BAK compression and SQL script generation --- .github/workflows/release.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3669e7d..563f87d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -110,18 +110,18 @@ jobs: Write-Warning "Failed to create BACPAC, continuing..." } - # Create .bak file with compatibility level for SQL Server 2016 + # Create .bak file with compatibility level for SQL Server 2016 (without compression for Express) Write-Host "Creating SQL Server 2016 compatible backup..." $bakFullPath = Join-Path $PWD $bakPath - sqlcmd -S $serverInstance -Q "ALTER DATABASE [$dbName] SET COMPATIBILITY_LEVEL = 130; BACKUP DATABASE [$dbName] TO DISK = N'$bakFullPath' WITH COMPRESSION, STATS = 10" + sqlcmd -S $serverInstance -Q "ALTER DATABASE [$dbName] SET COMPATIBILITY_LEVEL = 130; BACKUP DATABASE [$dbName] TO DISK = N'$bakFullPath' WITH STATS = 10" if ($LASTEXITCODE -ne 0) { Write-Warning "Failed to create BAK file, continuing..." } - # Generate SQL script from DACPAC (includes the compiled binary) + # Generate SQL deployment script from DACPAC Write-Host "Generating SQL script from DACPAC..." - & $sqlPackage /Action:Script /SourceFile:$dacpacPath /OutputPath:$generatedSqlPath /p:IncludeCompositeObjects=True + & $sqlPackage /Action:Script /SourceFile:$dacpacPath /TargetServerName:$serverInstance /TargetDatabaseName:"${dbName}_Script" /OutputPath:$generatedSqlPath /p:IncludeCompositeObjects=True /p:CommentOutSetVarDeclarations=True if ($LASTEXITCODE -ne 0) { Write-Warning "Failed to generate SQL script, continuing..." From 2c03c55089bf17b2d1ecc46eee67b138010507b4 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 13:13:55 +0100 Subject: [PATCH 07/37] Update assembly version to 0.3.8.0 --- Properties/AssemblyInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index e6de07d..f009e7c 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -19,5 +19,5 @@ // Numéro de build // Révision // -[assembly: AssemblyVersion("0.3.2.0")] -[assembly: AssemblyFileVersion("0.3.2.0")] +[assembly: AssemblyVersion("0.3.8.0")] +[assembly: AssemblyFileVersion("0.3.8.0")] From 79c2ed31cea9e439e1c2b6955657937db13fbb61 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 13:25:55 +0100 Subject: [PATCH 08/37] Add certificate-based security - eliminate TRUSTWORTHY requirement --- .github/workflows/release.yml | 127 +++++++++++++++++++++++++- INSTALLATION.md | 167 ++++++++++++++++++++++++++++++++++ 2 files changed, 291 insertions(+), 3 deletions(-) create mode 100644 INSTALLATION.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 563f87d..15f9643 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,6 +25,92 @@ jobs: - name: Build SQL Project run: msbuild FastWrappers_TSQL.sqlproj /p:Configuration=Release /p:Platform="Any CPU" /t:Build + - name: Create and Sign Assembly Certificate + shell: powershell + run: | + # Create self-signed certificate for SQL CLR assembly signing + Write-Host "Creating certificate for assembly signing..." + $cert = New-SelfSignedCertificate ` + -Type CodeSigningCert ` + -Subject "CN=FastWrappers SQLCLR Assembly" ` + -KeyExportPolicy Exportable ` + -CertStoreLocation "Cert:\CurrentUser\My" ` + -NotAfter (Get-Date).AddYears(10) ` + -KeyAlgorithm RSA ` + -KeyLength 2048 + + # Export public certificate for SQL Server + $certPath = "bin\Output\FastWrappers-Certificate.cer" + Export-Certificate -Cert $cert -FilePath $certPath -Force + Write-Host "Certificate exported to: $certPath" + + # Sign the compiled DLL + $dllPath = "bin\Output\FastWrappers_TSQL.dll" + if (Test-Path $dllPath) { + Write-Host "Signing assembly DLL..." + Set-AuthenticodeSignature -FilePath $dllPath -Certificate $cert -TimestampServer "http://timestamp.digicert.com" + Write-Host "Assembly signed successfully" + } else { + Write-Error "DLL not found at: $dllPath" + exit 1 + } + + # Get certificate thumbprint for documentation + $thumbprint = $cert.Thumbprint + Write-Host "Certificate Thumbprint: $thumbprint" + + - name: Generate Certificate Installation Script + shell: powershell + run: | + $installScript = @" + -- ============================================= + -- FastWrappers-TSQL Certificate Installation + -- ============================================= + -- This script must be run ONCE on each SQL Server instance + -- before deploying FastWrappers-TSQL databases. + -- + -- Prerequisites: + -- 1. Place FastWrappers-Certificate.cer in an accessible location + -- 2. Update the file path below to match your certificate location + -- 3. Run this script as sysadmin + -- ============================================= + + USE master; + GO + + -- Clean up existing certificate and login (if re-installing) + IF EXISTS (SELECT * FROM sys.server_principals WHERE name = 'FastWrappersLogin') + DROP LOGIN FastWrappersLogin; + GO + + IF EXISTS (SELECT * FROM sys.certificates WHERE name = 'FastWrappersCert') + DROP CERTIFICATE FastWrappersCert; + GO + + -- Create certificate from the .cer file + -- IMPORTANT: Update the path to where you placed the certificate file + CREATE CERTIFICATE FastWrappersCert + FROM FILE = 'C:\Path\To\FastWrappers-Certificate.cer'; + GO + + -- Create login from certificate + CREATE LOGIN FastWrappersLogin + FROM CERTIFICATE FastWrappersCert; + GO + + -- Grant UNSAFE ASSEMBLY permission to the login + GRANT UNSAFE ASSEMBLY TO FastWrappersLogin; + GO + + -- Verification + PRINT 'Certificate and login created successfully!'; + PRINT 'You can now deploy FastWrappers-TSQL databases without TRUSTWORTHY ON.'; + GO + "@ + + $installScript | Out-File -FilePath "bin\Output\Install-Certificate.sql" -Encoding UTF8 + Write-Host "Certificate installation script created" + - name: Verify Build Artifacts shell: powershell run: | @@ -153,7 +239,9 @@ jobs: @{Source="bin\Release\FastWrappers-TSQL.dacpac"; Name="FastWrappers-TSQL.dacpac"}, @{Source="bin\Release\FastWrappers-TSQL.bacpac"; Name="FastWrappers-TSQL.bacpac"}, @{Source="bin\Release\FastWrappers-TSQL.bak"; Name="FastWrappers-TSQL.bak"}, - @{Source="bin\Release\FastWrappers-TSQL.sql"; Name="FastWrappers-TSQL.sql"} + @{Source="bin\Release\FastWrappers-TSQL.sql"; Name="FastWrappers-TSQL.sql"}, + @{Source="bin\Output\FastWrappers-Certificate.cer"; Name="FastWrappers-Certificate.cer"}, + @{Source="bin\Output\Install-Certificate.sql"; Name="Install-Certificate.sql"} ) foreach ($file in $files) { @@ -176,15 +264,48 @@ jobs: body: | ## FastWrappers-TSQL v${{ steps.get_version.outputs.VERSION }} - ### Installation Methods + ### 🔒 Security Notice - Certificate-Based Installation (No TRUSTWORTHY Required!) + + This release includes a **signed assembly** that eliminates the need for `TRUSTWORTHY ON`. + + #### One-Time Server Setup (Required Before First Use) + + 1. Download `FastWrappers-Certificate.cer` and `Install-Certificate.sql` + 2. Place the certificate file in an accessible location (e.g., `C:\Certificates\`) + 3. Edit `Install-Certificate.sql` and update the certificate file path + 4. Run `Install-Certificate.sql` as **sysadmin** on your SQL Server instance + + **This setup is done ONCE per SQL Server instance.** - This release provides multiple installation options: + #### After Certificate Installation + + You can then deploy FastWrappers-TSQL using any method below **WITHOUT** `TRUSTWORTHY ON`: + + --- + + ### 📦 Installation Methods - **FastWrappers-TSQL.dacpac** - Data-tier Application Package (recommended for Visual Studio / SQL Server Data Tools) - **FastWrappers-TSQL.bacpac** - Binary Application Package (for import/export between servers) - **FastWrappers-TSQL.bak** - SQL Server Backup (compatible with SQL Server 2016+, restore using SSMS) - **FastWrappers-TSQL.sql** - Pure SQL Script (execute using sqlcmd or SSMS) + ### 🔐 Security Files + + - **FastWrappers-Certificate.cer** - Public certificate for SQL Server (required for installation) + - **Install-Certificate.sql** - Installation script for certificate setup + + ### ⚙️ Server Configuration + + Once the certificate is installed, you still need to enable CLR: + + ```sql + EXEC sp_configure 'show advanced options', 1; + RECONFIGURE; + EXEC sp_configure 'clr enabled', 1; + RECONFIGURE; + ``` + ### Usage See [README.md](https://github.com/${{ github.repository }}/blob/main/README.md) for usage examples. diff --git a/INSTALLATION.md b/INSTALLATION.md new file mode 100644 index 0000000..c4e8705 --- /dev/null +++ b/INSTALLATION.md @@ -0,0 +1,167 @@ +# FastWrappers-TSQL Installation Guide + +## 🔒 Secure Installation (Recommended) + +FastWrappers-TSQL uses **certificate-based security** to eliminate the need for `TRUSTWORTHY ON`, following SQL Server security best practices. + +### Prerequisites + +- SQL Server 2016 or later +- Sysadmin privileges for initial certificate installation +- CLR enabled on the SQL Server instance + +--- + +## Step 1: One-Time Server Setup (Certificate Installation) + +**This step is performed ONCE per SQL Server instance.** + +### 1.1 Download Required Files + +From the [latest release](https://github.com/PierreAntoineAP/FastWrappers-TSQL-Dev/releases/latest), download: +- `FastWrappers-Certificate.cer` +- `Install-Certificate.sql` + +### 1.2 Place the Certificate + +Copy `FastWrappers-Certificate.cer` to a secure location on your server, for example: +- `C:\Certificates\FastWrappers-Certificate.cer` + +### 1.3 Update and Run Installation Script + +1. Open `Install-Certificate.sql` in SQL Server Management Studio +2. Update the file path on line 24: + ```sql + CREATE CERTIFICATE FastWrappersCert + FROM FILE = 'C:\Certificates\FastWrappers-Certificate.cer'; -- Update this path + ``` +3. Execute the script as **sysadmin** + +**What this does:** +- Creates a certificate in `master` database +- Creates a login trusted for UNSAFE assemblies +- Grants necessary permissions + +### 1.4 Enable CLR (If Not Already Enabled) + +```sql +EXEC sp_configure 'show advanced options', 1; +RECONFIGURE; +GO + +EXEC sp_configure 'clr enabled', 1; +RECONFIGURE; +GO +``` + +✅ **Server setup complete!** You can now deploy FastWrappers-TSQL to any database on this server. + +--- + +## Step 2: Deploy FastWrappers-TSQL Database + +After the certificate is installed, choose one of the following deployment methods: + +### Option A: Restore from Backup (.bak) + +```sql +RESTORE DATABASE [FastWrappers-TSQL] +FROM DISK = N'C:\Path\To\FastWrappers-TSQL.bak' +WITH MOVE 'FastWrappers-TSQL' TO 'C:\SQLData\FastWrappers-TSQL.mdf', + MOVE 'FastWrappers-TSQL_log' TO 'C:\SQLData\FastWrappers-TSQL_log.ldf', + REPLACE; +GO +``` + +### Option B: Deploy DACPAC (Visual Studio/SqlPackage) + +```powershell +SqlPackage.exe /Action:Publish ` + /SourceFile:"FastWrappers-TSQL.dacpac" ` + /TargetServerName:"YourServer" ` + /TargetDatabaseName:"FastWrappers-TSQL" +``` + +### Option C: Import BACPAC + +1. Open SQL Server Management Studio +2. Right-click on **Databases** → **Import Data-tier Application** +3. Select `FastWrappers-TSQL.bacpac` +4. Follow the wizard + +### Option D: Execute SQL Script + +```sql +-- Run FastWrappers-TSQL.sql in SQLCMD mode or SSMS +:r C:\Path\To\FastWrappers-TSQL.sql +``` + +--- + +## Step 3: Verify Installation + +```sql +USE [FastWrappers-TSQL]; +GO + +-- Test encryption function +SELECT dbo.EncryptString('test123') AS EncryptedValue; +GO + +-- Should return an encrypted base64 string +``` + +If this works without errors, installation is successful! ✅ + +--- + +## Security Benefits + +✅ **No TRUSTWORTHY ON required** - More secure database configuration +✅ **Certificate-based security** - Industry best practice +✅ **Server-level trust** - Deploy to multiple databases easily +✅ **Audit-friendly** - Clear security chain of trust + +--- + +## Troubleshooting + +### Error: "Assembly may not be trusted" (0x80FC80F1) + +**Cause:** Certificate not installed on the server. + +**Solution:** Complete Step 1 (Certificate Installation) + +### Error: "Could not load file or assembly" + +**Cause:** CLR not enabled. + +**Solution:** +```sql +EXEC sp_configure 'clr enabled', 1; +RECONFIGURE; +``` + +### Error: "CREATE CERTIFICATE failed" + +**Cause:** File path incorrect or insufficient permissions. + +**Solution:** +- Verify the certificate file path +- Ensure SQL Server service account can read the file +- Run as sysadmin + +--- + +## Updating to a New Version + +When a new version is released: + +1. **If the certificate hasn't changed:** Simply deploy the new database files (no server setup needed) +2. **If a new certificate is included:** Re-run Step 1 with the new certificate + +--- + +## Support + +For issues or questions, please open an issue on [GitHub](https://github.com/PierreAntoineAP/FastWrappers-TSQL-Dev/issues). From af98fc10280742c5d1036a6185c8d19d5e2e6ef4 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 13:38:19 +0100 Subject: [PATCH 09/37] Revert certificate approach - use TRUSTWORTHY ON --- .github/workflows/release.yml | 127 +++----------------------- INSTALLATION.md | 167 ---------------------------------- 2 files changed, 13 insertions(+), 281 deletions(-) delete mode 100644 INSTALLATION.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 15f9643..b03f502 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,92 +25,6 @@ jobs: - name: Build SQL Project run: msbuild FastWrappers_TSQL.sqlproj /p:Configuration=Release /p:Platform="Any CPU" /t:Build - - name: Create and Sign Assembly Certificate - shell: powershell - run: | - # Create self-signed certificate for SQL CLR assembly signing - Write-Host "Creating certificate for assembly signing..." - $cert = New-SelfSignedCertificate ` - -Type CodeSigningCert ` - -Subject "CN=FastWrappers SQLCLR Assembly" ` - -KeyExportPolicy Exportable ` - -CertStoreLocation "Cert:\CurrentUser\My" ` - -NotAfter (Get-Date).AddYears(10) ` - -KeyAlgorithm RSA ` - -KeyLength 2048 - - # Export public certificate for SQL Server - $certPath = "bin\Output\FastWrappers-Certificate.cer" - Export-Certificate -Cert $cert -FilePath $certPath -Force - Write-Host "Certificate exported to: $certPath" - - # Sign the compiled DLL - $dllPath = "bin\Output\FastWrappers_TSQL.dll" - if (Test-Path $dllPath) { - Write-Host "Signing assembly DLL..." - Set-AuthenticodeSignature -FilePath $dllPath -Certificate $cert -TimestampServer "http://timestamp.digicert.com" - Write-Host "Assembly signed successfully" - } else { - Write-Error "DLL not found at: $dllPath" - exit 1 - } - - # Get certificate thumbprint for documentation - $thumbprint = $cert.Thumbprint - Write-Host "Certificate Thumbprint: $thumbprint" - - - name: Generate Certificate Installation Script - shell: powershell - run: | - $installScript = @" - -- ============================================= - -- FastWrappers-TSQL Certificate Installation - -- ============================================= - -- This script must be run ONCE on each SQL Server instance - -- before deploying FastWrappers-TSQL databases. - -- - -- Prerequisites: - -- 1. Place FastWrappers-Certificate.cer in an accessible location - -- 2. Update the file path below to match your certificate location - -- 3. Run this script as sysadmin - -- ============================================= - - USE master; - GO - - -- Clean up existing certificate and login (if re-installing) - IF EXISTS (SELECT * FROM sys.server_principals WHERE name = 'FastWrappersLogin') - DROP LOGIN FastWrappersLogin; - GO - - IF EXISTS (SELECT * FROM sys.certificates WHERE name = 'FastWrappersCert') - DROP CERTIFICATE FastWrappersCert; - GO - - -- Create certificate from the .cer file - -- IMPORTANT: Update the path to where you placed the certificate file - CREATE CERTIFICATE FastWrappersCert - FROM FILE = 'C:\Path\To\FastWrappers-Certificate.cer'; - GO - - -- Create login from certificate - CREATE LOGIN FastWrappersLogin - FROM CERTIFICATE FastWrappersCert; - GO - - -- Grant UNSAFE ASSEMBLY permission to the login - GRANT UNSAFE ASSEMBLY TO FastWrappersLogin; - GO - - -- Verification - PRINT 'Certificate and login created successfully!'; - PRINT 'You can now deploy FastWrappers-TSQL databases without TRUSTWORTHY ON.'; - GO - "@ - - $installScript | Out-File -FilePath "bin\Output\Install-Certificate.sql" -Encoding UTF8 - Write-Host "Certificate installation script created" - - name: Verify Build Artifacts shell: powershell run: | @@ -239,9 +153,7 @@ jobs: @{Source="bin\Release\FastWrappers-TSQL.dacpac"; Name="FastWrappers-TSQL.dacpac"}, @{Source="bin\Release\FastWrappers-TSQL.bacpac"; Name="FastWrappers-TSQL.bacpac"}, @{Source="bin\Release\FastWrappers-TSQL.bak"; Name="FastWrappers-TSQL.bak"}, - @{Source="bin\Release\FastWrappers-TSQL.sql"; Name="FastWrappers-TSQL.sql"}, - @{Source="bin\Output\FastWrappers-Certificate.cer"; Name="FastWrappers-Certificate.cer"}, - @{Source="bin\Output\Install-Certificate.sql"; Name="Install-Certificate.sql"} + @{Source="bin\Release\FastWrappers-TSQL.sql"; Name="FastWrappers-TSQL.sql"} ) foreach ($file in $files) { @@ -264,46 +176,33 @@ jobs: body: | ## FastWrappers-TSQL v${{ steps.get_version.outputs.VERSION }} - ### 🔒 Security Notice - Certificate-Based Installation (No TRUSTWORTHY Required!) - - This release includes a **signed assembly** that eliminates the need for `TRUSTWORTHY ON`. - - #### One-Time Server Setup (Required Before First Use) - - 1. Download `FastWrappers-Certificate.cer` and `Install-Certificate.sql` - 2. Place the certificate file in an accessible location (e.g., `C:\Certificates\`) - 3. Edit `Install-Certificate.sql` and update the certificate file path - 4. Run `Install-Certificate.sql` as **sysadmin** on your SQL Server instance + ### Installation Methods - **This setup is done ONCE per SQL Server instance.** - - #### After Certificate Installation - - You can then deploy FastWrappers-TSQL using any method below **WITHOUT** `TRUSTWORTHY ON`: - - --- - - ### 📦 Installation Methods + This release provides multiple installation options: - **FastWrappers-TSQL.dacpac** - Data-tier Application Package (recommended for Visual Studio / SQL Server Data Tools) - **FastWrappers-TSQL.bacpac** - Binary Application Package (for import/export between servers) - **FastWrappers-TSQL.bak** - SQL Server Backup (compatible with SQL Server 2016+, restore using SSMS) - **FastWrappers-TSQL.sql** - Pure SQL Script (execute using sqlcmd or SSMS) - ### 🔐 Security Files + ### Prerequisites - - **FastWrappers-Certificate.cer** - Public certificate for SQL Server (required for installation) - - **Install-Certificate.sql** - Installation script for certificate setup + After deployment, you must enable CLR and set TRUSTWORTHY: - ### ⚙️ Server Configuration + ```sql + USE [FastWrappers-TSQL]; + GO - Once the certificate is installed, you still need to enable CLR: + ALTER DATABASE [FastWrappers-TSQL] SET TRUSTWORTHY ON; + GO - ```sql EXEC sp_configure 'show advanced options', 1; RECONFIGURE; + GO + EXEC sp_configure 'clr enabled', 1; RECONFIGURE; + GO ``` ### Usage diff --git a/INSTALLATION.md b/INSTALLATION.md deleted file mode 100644 index c4e8705..0000000 --- a/INSTALLATION.md +++ /dev/null @@ -1,167 +0,0 @@ -# FastWrappers-TSQL Installation Guide - -## 🔒 Secure Installation (Recommended) - -FastWrappers-TSQL uses **certificate-based security** to eliminate the need for `TRUSTWORTHY ON`, following SQL Server security best practices. - -### Prerequisites - -- SQL Server 2016 or later -- Sysadmin privileges for initial certificate installation -- CLR enabled on the SQL Server instance - ---- - -## Step 1: One-Time Server Setup (Certificate Installation) - -**This step is performed ONCE per SQL Server instance.** - -### 1.1 Download Required Files - -From the [latest release](https://github.com/PierreAntoineAP/FastWrappers-TSQL-Dev/releases/latest), download: -- `FastWrappers-Certificate.cer` -- `Install-Certificate.sql` - -### 1.2 Place the Certificate - -Copy `FastWrappers-Certificate.cer` to a secure location on your server, for example: -- `C:\Certificates\FastWrappers-Certificate.cer` - -### 1.3 Update and Run Installation Script - -1. Open `Install-Certificate.sql` in SQL Server Management Studio -2. Update the file path on line 24: - ```sql - CREATE CERTIFICATE FastWrappersCert - FROM FILE = 'C:\Certificates\FastWrappers-Certificate.cer'; -- Update this path - ``` -3. Execute the script as **sysadmin** - -**What this does:** -- Creates a certificate in `master` database -- Creates a login trusted for UNSAFE assemblies -- Grants necessary permissions - -### 1.4 Enable CLR (If Not Already Enabled) - -```sql -EXEC sp_configure 'show advanced options', 1; -RECONFIGURE; -GO - -EXEC sp_configure 'clr enabled', 1; -RECONFIGURE; -GO -``` - -✅ **Server setup complete!** You can now deploy FastWrappers-TSQL to any database on this server. - ---- - -## Step 2: Deploy FastWrappers-TSQL Database - -After the certificate is installed, choose one of the following deployment methods: - -### Option A: Restore from Backup (.bak) - -```sql -RESTORE DATABASE [FastWrappers-TSQL] -FROM DISK = N'C:\Path\To\FastWrappers-TSQL.bak' -WITH MOVE 'FastWrappers-TSQL' TO 'C:\SQLData\FastWrappers-TSQL.mdf', - MOVE 'FastWrappers-TSQL_log' TO 'C:\SQLData\FastWrappers-TSQL_log.ldf', - REPLACE; -GO -``` - -### Option B: Deploy DACPAC (Visual Studio/SqlPackage) - -```powershell -SqlPackage.exe /Action:Publish ` - /SourceFile:"FastWrappers-TSQL.dacpac" ` - /TargetServerName:"YourServer" ` - /TargetDatabaseName:"FastWrappers-TSQL" -``` - -### Option C: Import BACPAC - -1. Open SQL Server Management Studio -2. Right-click on **Databases** → **Import Data-tier Application** -3. Select `FastWrappers-TSQL.bacpac` -4. Follow the wizard - -### Option D: Execute SQL Script - -```sql --- Run FastWrappers-TSQL.sql in SQLCMD mode or SSMS -:r C:\Path\To\FastWrappers-TSQL.sql -``` - ---- - -## Step 3: Verify Installation - -```sql -USE [FastWrappers-TSQL]; -GO - --- Test encryption function -SELECT dbo.EncryptString('test123') AS EncryptedValue; -GO - --- Should return an encrypted base64 string -``` - -If this works without errors, installation is successful! ✅ - ---- - -## Security Benefits - -✅ **No TRUSTWORTHY ON required** - More secure database configuration -✅ **Certificate-based security** - Industry best practice -✅ **Server-level trust** - Deploy to multiple databases easily -✅ **Audit-friendly** - Clear security chain of trust - ---- - -## Troubleshooting - -### Error: "Assembly may not be trusted" (0x80FC80F1) - -**Cause:** Certificate not installed on the server. - -**Solution:** Complete Step 1 (Certificate Installation) - -### Error: "Could not load file or assembly" - -**Cause:** CLR not enabled. - -**Solution:** -```sql -EXEC sp_configure 'clr enabled', 1; -RECONFIGURE; -``` - -### Error: "CREATE CERTIFICATE failed" - -**Cause:** File path incorrect or insufficient permissions. - -**Solution:** -- Verify the certificate file path -- Ensure SQL Server service account can read the file -- Run as sysadmin - ---- - -## Updating to a New Version - -When a new version is released: - -1. **If the certificate hasn't changed:** Simply deploy the new database files (no server setup needed) -2. **If a new certificate is included:** Re-run Step 1 with the new certificate - ---- - -## Support - -For issues or questions, please open an issue on [GitHub](https://github.com/PierreAntoineAP/FastWrappers-TSQL-Dev/issues). From 4d8b4045e486e92db224ca82a84387ba285f9086 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 13:39:50 +0100 Subject: [PATCH 10/37] Target .NET Framework 4.0 for SQL Server 2016 compatibility --- FastWrappers_TSQL.sqlproj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/FastWrappers_TSQL.sqlproj b/FastWrappers_TSQL.sqlproj index 6445cda..ddd9eec 100644 --- a/FastWrappers_TSQL.sqlproj +++ b/FastWrappers_TSQL.sqlproj @@ -16,7 +16,7 @@ 1033, CI BySchemaAndSchemaType True - v4.8.1 + v4.0 CS Properties False @@ -32,7 +32,6 @@ AetPCLRSign.pfx.snk True procedures de wrapping pour FastTransfer et FastBCP - 2.0.0.0 From 8785df3fb01580eecdf7fcaf1b673180b46498c3 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 13:43:34 +0100 Subject: [PATCH 11/37] Use .NET Framework 4.6.2 (available on GitHub Actions) --- FastWrappers_TSQL.sqlproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FastWrappers_TSQL.sqlproj b/FastWrappers_TSQL.sqlproj index ddd9eec..a2c2534 100644 --- a/FastWrappers_TSQL.sqlproj +++ b/FastWrappers_TSQL.sqlproj @@ -16,7 +16,7 @@ 1033, CI BySchemaAndSchemaType True - v4.0 + v4.6.2 CS Properties False From 0fbe4749db533dbbcac10105ed1efd33d0258678 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 13:53:22 +0100 Subject: [PATCH 12/37] Remove assembly signing to fix 0x80FC80F1 error --- FastWrappers_TSQL.sqlproj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/FastWrappers_TSQL.sqlproj b/FastWrappers_TSQL.sqlproj index a2c2534..432581d 100644 --- a/FastWrappers_TSQL.sqlproj +++ b/FastWrappers_TSQL.sqlproj @@ -28,8 +28,7 @@ True UNSAFE dbo - True - AetPCLRSign.pfx.snk + False True procedures de wrapping pour FastTransfer et FastBCP 2.0.0.0 From 9d0f22c8cbac4d15096410da34ac7725d0459a7e Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 14:14:40 +0100 Subject: [PATCH 13/37] =?UTF-8?q?v0.5.0=20-=20Retour=20=C3=A0=20la=20confi?= =?UTF-8?q?guration=20d'origine=20(.NET=204.8.1,=20SQL=20Server=202022,=20?= =?UTF-8?q?assembly=20sign=C3=A9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 31 +++++++++++++++---------------- AetPCLRSign.pfx.snk.backup | Bin 0 -> 596 bytes FastWrappers_TSQL.sqlproj | 7 ++++--- Properties/AssemblyInfo.cs | 4 ++-- 4 files changed, 21 insertions(+), 21 deletions(-) create mode 100644 AetPCLRSign.pfx.snk.backup diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b03f502..0131405 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -110,10 +110,10 @@ jobs: Write-Warning "Failed to create BACPAC, continuing..." } - # Create .bak file with compatibility level for SQL Server 2016 (without compression for Express) - Write-Host "Creating SQL Server 2016 compatible backup..." + # Create backup file + Write-Host "Creating SQL Server backup..." $bakFullPath = Join-Path $PWD $bakPath - sqlcmd -S $serverInstance -Q "ALTER DATABASE [$dbName] SET COMPATIBILITY_LEVEL = 130; BACKUP DATABASE [$dbName] TO DISK = N'$bakFullPath' WITH STATS = 10" + sqlcmd -S $serverInstance -Q "BACKUP DATABASE [$dbName] TO DISK = N'$bakFullPath' WITH STATS = 10" if ($LASTEXITCODE -ne 0) { Write-Warning "Failed to create BAK file, continuing..." @@ -176,38 +176,37 @@ jobs: body: | ## FastWrappers-TSQL v${{ steps.get_version.outputs.VERSION }} - ### Installation Methods + ### Installation Files - This release provides multiple installation options: - - - **FastWrappers-TSQL.dacpac** - Data-tier Application Package (recommended for Visual Studio / SQL Server Data Tools) + - **FastWrappers-TSQL.dacpac** - Data-tier Application Package (for Visual Studio / SQL Server Data Tools) - **FastWrappers-TSQL.bacpac** - Binary Application Package (for import/export between servers) - - **FastWrappers-TSQL.bak** - SQL Server Backup (compatible with SQL Server 2016+, restore using SSMS) - - **FastWrappers-TSQL.sql** - Pure SQL Script (execute using sqlcmd or SSMS) - - ### Prerequisites + - **FastWrappers-TSQL.bak** - SQL Server Backup (restore using SSMS) + - **FastWrappers-TSQL.sql** - SQL Script (execute using sqlcmd or SSMS) - After deployment, you must enable CLR and set TRUSTWORTHY: + ### Installation + **Option 1: Restore from backup (.bak file)** ```sql - USE [FastWrappers-TSQL]; + RESTORE DATABASE [FastWrappers-TSQL] FROM DISK = 'FastWrappers-TSQL.bak'; GO + -- Enable TRUSTWORTHY and CLR ALTER DATABASE [FastWrappers-TSQL] SET TRUSTWORTHY ON; GO EXEC sp_configure 'show advanced options', 1; RECONFIGURE; - GO - EXEC sp_configure 'clr enabled', 1; RECONFIGURE; GO ``` + **Option 2: Deploy DACPAC** + Use SqlPackage or Visual Studio to deploy the .dacpac file. + ### Usage - See [README.md](https://github.com/${{ github.repository }}/blob/main/README.md) for usage examples. + See [README.md](https://github.com/${{ github.repository }}/blob/main/README.md) for examples. files: | release/* draft: false diff --git a/AetPCLRSign.pfx.snk.backup b/AetPCLRSign.pfx.snk.backup new file mode 100644 index 0000000000000000000000000000000000000000..45bb1a37c869f723e707aaaf76e8cf537d2e966a GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50096&s|-?(RCw~sl)l1`gq3TpKPn)NY}_I1 z`b+IAPprOFKW}DyY0+7EQQkTor-K8=hsF0F{c2~!{!+yo&^cd0W6l_TCug zzVUK~sy5wDQnj&R2i7-26c^2oU9KI_tFk|kk52Lfv|T$}YfC5B@7>~BLSFLf}XaD~m<%JcyM4T~QBrN0>5*eTQopgV{4 zZw5z;Qe}Uw$8FJ*BszrnHi|p>tkARgqA|-DvxQ9^y2$%y6K1Bt$JBgzF|(sYp?Oh% zEm)xJO??Xj^T6}1YT0!qt)QCI!wUbS|K2J(=-qcBm^)(Pm%LtdvT-s2#c!z=4OEu8 zHm8dtSM!3{E;*sg_)r2)O?96oNHy?}{6JN2RueOspFdUU@hXz92r%{hfR}J?qYR1q z`6~@bpfqV4+!;qoRl{2TAx7bpEHc+Db$1Bf(<$w=Gaj~`mL#&YNhmbmjU+MLg#IHA zKQz}5ipEa~%9Z5M75N1Hq(l7kH?%_lp z4VFbiq7=myD_yGj<+^wl7|UWFX8^ckGVa7|@RzGXqR1K19K-5uzRsr*^R(F$JuC+aLP{ iBAXsFQbCbhpN{;rV|0o7+W*-+1r7C1^NX)&mYJI302ECC literal 0 HcmV?d00001 diff --git a/FastWrappers_TSQL.sqlproj b/FastWrappers_TSQL.sqlproj index 432581d..1533a57 100644 --- a/FastWrappers_TSQL.sqlproj +++ b/FastWrappers_TSQL.sqlproj @@ -7,7 +7,7 @@ 2.0 4.1 {4b096d13-154a-472c-9882-f281334958f9} - Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider + Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider Database @@ -16,7 +16,7 @@ 1033, CI BySchemaAndSchemaType True - v4.6.2 + v4.8.1 CS Properties False @@ -28,7 +28,8 @@ True UNSAFE dbo - False + True + AetPCLRSign.pfx.snk True procedures de wrapping pour FastTransfer et FastBCP 2.0.0.0 diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index f009e7c..91e3aae 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -19,5 +19,5 @@ // Numéro de build // Révision // -[assembly: AssemblyVersion("0.3.8.0")] -[assembly: AssemblyFileVersion("0.3.8.0")] +[assembly: AssemblyVersion("0.5.0.0")] +[assembly: AssemblyFileVersion("0.5.0.0")] From a4f19efdaf6b4531bbe64151613c82e2e3f10785 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 14:16:50 +0100 Subject: [PATCH 14/37] Remove backup of assembly signing key --- AetPCLRSign.pfx.snk.backup | Bin 596 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 AetPCLRSign.pfx.snk.backup diff --git a/AetPCLRSign.pfx.snk.backup b/AetPCLRSign.pfx.snk.backup deleted file mode 100644 index 45bb1a37c869f723e707aaaf76e8cf537d2e966a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50096&s|-?(RCw~sl)l1`gq3TpKPn)NY}_I1 z`b+IAPprOFKW}DyY0+7EQQkTor-K8=hsF0F{c2~!{!+yo&^cd0W6l_TCug zzVUK~sy5wDQnj&R2i7-26c^2oU9KI_tFk|kk52Lfv|T$}YfC5B@7>~BLSFLf}XaD~m<%JcyM4T~QBrN0>5*eTQopgV{4 zZw5z;Qe}Uw$8FJ*BszrnHi|p>tkARgqA|-DvxQ9^y2$%y6K1Bt$JBgzF|(sYp?Oh% zEm)xJO??Xj^T6}1YT0!qt)QCI!wUbS|K2J(=-qcBm^)(Pm%LtdvT-s2#c!z=4OEu8 zHm8dtSM!3{E;*sg_)r2)O?96oNHy?}{6JN2RueOspFdUU@hXz92r%{hfR}J?qYR1q z`6~@bpfqV4+!;qoRl{2TAx7bpEHc+Db$1Bf(<$w=Gaj~`mL#&YNhmbmjU+MLg#IHA zKQz}5ipEa~%9Z5M75N1Hq(l7kH?%_lp z4VFbiq7=myD_yGj<+^wl7|UWFX8^ckGVa7|@RzGXqR1K19K-5uzRsr*^R(F$JuC+aLP{ iBAXsFQbCbhpN{;rV|0o7+W*-+1r7C1^NX)&mYJI302ECC From 2fe3c40f4518765c0918597533d7c19e96051251 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 14:17:49 +0100 Subject: [PATCH 15/37] =?UTF-8?q?v0.5.1=20-=20Cibler=20SQL=20Server=202016?= =?UTF-8?q?=20pour=20compatibilit=C3=A9=20LocalDB=202019?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastWrappers_TSQL.sqlproj | 2 +- Properties/AssemblyInfo.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/FastWrappers_TSQL.sqlproj b/FastWrappers_TSQL.sqlproj index 1533a57..fba5dd7 100644 --- a/FastWrappers_TSQL.sqlproj +++ b/FastWrappers_TSQL.sqlproj @@ -7,7 +7,7 @@ 2.0 4.1 {4b096d13-154a-472c-9882-f281334958f9} - Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider + Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider Database diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index 91e3aae..697e719 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -19,5 +19,5 @@ // Numéro de build // Révision // -[assembly: AssemblyVersion("0.5.0.0")] -[assembly: AssemblyFileVersion("0.5.0.0")] +[assembly: AssemblyVersion("0.5.1.0")] +[assembly: AssemblyFileVersion("0.5.1.0")] From 33b94cbc196b126a3ec879efe7fc6e3353b71bca Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 16:44:18 +0100 Subject: [PATCH 16/37] v0.5.2 - Ajout support trusted assembly pour SQL Server 2017+ (clr strict security) --- .github/workflows/release.yml | 144 ++++++++++++++++++++++++++++++---- FastWrappers_TSQL.sqlproj | 5 +- Properties/AssemblyInfo.cs | 4 +- 3 files changed, 133 insertions(+), 20 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0131405..7eb95b3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -90,6 +90,24 @@ jobs: $sqlPackage = "SqlPackage\SqlPackage.exe" + # Calculate SHA2-512 hash of the DLL for trusted assembly + $dllPath = "bin\Output\FastWrappers_TSQL.dll" + Write-Host "Calculating SHA2-512 hash for trusted assembly..." + $dllBytes = [System.IO.File]::ReadAllBytes((Resolve-Path $dllPath).Path) + $sha512 = [System.Security.Cryptography.SHA512]::Create() + $hashBytes = $sha512.ComputeHash($dllBytes) + $hashHex = [System.BitConverter]::ToString($hashBytes).Replace("-", "") + Write-Host "DLL Hash: 0x$hashHex" + + # Add assembly as trusted before deployment (for SQL Server 2017+ with clr strict security) + Write-Host "Adding assembly as trusted..." + $addTrustedAssembly = @" +EXEC sys.sp_add_trusted_assembly + @hash = 0x$hashHex, + @description = N'FastWrappers_TSQL - CLR Wrapper for FastTransfer and FastBCP'; +"@ + sqlcmd -S $serverInstance -Q $addTrustedAssembly + # Deploy the DACPAC to create the database Write-Host "Deploying DACPAC to create database..." & $sqlPackage /Action:Publish /SourceFile:$dacpacPath /TargetServerName:$serverInstance /TargetDatabaseName:$dbName /p:IncludeCompositeObjects=True @@ -119,9 +137,74 @@ jobs: Write-Warning "Failed to create BAK file, continuing..." } - # Generate SQL deployment script from DACPAC + # Generate installation script with trusted assembly setup + Write-Host "Generating installation script with trusted assembly..." + $installScriptPath = "$outputDir\Install-TrustedAssembly.sql" + $installScript = @" +-- ============================================= +-- FastWrappers-TSQL Installation Script +-- For SQL Server 2017+ with CLR Strict Security +-- ============================================= +-- This script must be run as sysadmin +-- ============================================= + +USE master; +GO + +-- Check SQL Server version and clr strict security +DECLARE @version INT = CAST(SERVERPROPERTY('ProductMajorVersion') AS INT); +DECLARE @strictSec INT; + +EXEC sp_configure 'show advanced options', 1; +RECONFIGURE; + +SELECT @strictSec = CAST(value_in_use AS INT) +FROM sys.configurations +WHERE name = 'clr strict security'; + +PRINT 'SQL Server Version: ' + CAST(@version AS VARCHAR); +PRINT 'CLR Strict Security: ' + CAST(@strictSec AS VARCHAR); + +-- Enable CLR +EXEC sp_configure 'clr enabled', 1; +RECONFIGURE; +GO + +-- Add FastWrappers_TSQL as trusted assembly (SQL Server 2017+) +-- This allows the assembly to load even with clr strict security enabled +IF NOT EXISTS (SELECT 1 FROM sys.trusted_assemblies WHERE [hash] = 0x$hashHex) +BEGIN + EXEC sys.sp_add_trusted_assembly + @hash = 0x$hashHex, + @description = N'FastWrappers_TSQL, Version=0.5.1.0, Culture=neutral, PublicKeyToken=53f6bd85035abe03'; + PRINT 'Added FastWrappers_TSQL as trusted assembly'; +END +ELSE +BEGIN + PRINT 'FastWrappers_TSQL already in trusted assemblies'; +END +GO + +-- Now restore the database or deploy DACPAC +-- Example for backup restore: +-- RESTORE DATABASE [FastWrappers-TSQL] FROM DISK = 'FastWrappers-TSQL.bak'; +-- GO + +-- Set TRUSTWORTHY ON (still required for UNSAFE assemblies) +-- ALTER DATABASE [FastWrappers-TSQL] SET TRUSTWORTHY ON; +-- GO + +-- Test +-- USE [FastWrappers-TSQL]; +-- SELECT dbo.EncryptString('test'); +"@ + + $installScript | Out-File -FilePath $installScriptPath -Encoding UTF8 + Write-Host "Installation script created: $installScriptPath" + + # Generate SQL script from DACPAC (includes the compiled binary) Write-Host "Generating SQL script from DACPAC..." - & $sqlPackage /Action:Script /SourceFile:$dacpacPath /TargetServerName:$serverInstance /TargetDatabaseName:"${dbName}_Script" /OutputPath:$generatedSqlPath /p:IncludeCompositeObjects=True /p:CommentOutSetVarDeclarations=True + & $sqlPackage /Action:Script /SourceFile:$dacpacPath /OutputPath:$generatedSqlPath /p:IncludeCompositeObjects=True if ($LASTEXITCODE -ne 0) { Write-Warning "Failed to generate SQL script, continuing..." @@ -153,7 +236,8 @@ jobs: @{Source="bin\Release\FastWrappers-TSQL.dacpac"; Name="FastWrappers-TSQL.dacpac"}, @{Source="bin\Release\FastWrappers-TSQL.bacpac"; Name="FastWrappers-TSQL.bacpac"}, @{Source="bin\Release\FastWrappers-TSQL.bak"; Name="FastWrappers-TSQL.bak"}, - @{Source="bin\Release\FastWrappers-TSQL.sql"; Name="FastWrappers-TSQL.sql"} + @{Source="bin\Release\FastWrappers-TSQL.sql"; Name="FastWrappers-TSQL.sql"}, + @{Source="bin\Release\Install-TrustedAssembly.sql"; Name="Install-TrustedAssembly.sql"} ) foreach ($file in $files) { @@ -176,37 +260,65 @@ jobs: body: | ## FastWrappers-TSQL v${{ steps.get_version.outputs.VERSION }} - ### Installation Files + ### 📦 Installation Files + - **Install-TrustedAssembly.sql** - ⭐ **REQUIRED FIRST** for SQL Server 2017+ (adds assembly to trusted list) - **FastWrappers-TSQL.dacpac** - Data-tier Application Package (for Visual Studio / SQL Server Data Tools) - **FastWrappers-TSQL.bacpac** - Binary Application Package (for import/export between servers) - - **FastWrappers-TSQL.bak** - SQL Server Backup (restore using SSMS) + - **FastWrappers-TSQL.bak** - SQL Server Backup (compatible with SQL Server 2016+, restore using SSMS) - **FastWrappers-TSQL.sql** - SQL Script (execute using sqlcmd or SSMS) - ### Installation + ### 🚀 Installation Instructions - **Option 1: Restore from backup (.bak file)** + #### For SQL Server 2017+ (with CLR Strict Security) + + **Step 1: Run Install-TrustedAssembly.sql first** (as sysadmin) + ```sql + -- This adds the assembly to sys.trusted_assemblies + -- Run this once per SQL Server instance + sqlcmd -S YourServer -E -i Install-TrustedAssembly.sql + ``` + + **Step 2: Restore database** ```sql RESTORE DATABASE [FastWrappers-TSQL] FROM DISK = 'FastWrappers-TSQL.bak'; GO - -- Enable TRUSTWORTHY and CLR ALTER DATABASE [FastWrappers-TSQL] SET TRUSTWORTHY ON; GO + ``` + + **Step 3: Test** + ```sql + USE [FastWrappers-TSQL]; + SELECT dbo.EncryptString('test'); + ``` - EXEC sp_configure 'show advanced options', 1; - RECONFIGURE; - EXEC sp_configure 'clr enabled', 1; - RECONFIGURE; + #### For SQL Server 2016 or with CLR Strict Security disabled + + ```sql + -- Enable CLR + EXEC sp_configure 'show advanced options', 1; RECONFIGURE; + EXEC sp_configure 'clr enabled', 1; RECONFIGURE; + GO + + -- Restore database + RESTORE DATABASE [FastWrappers-TSQL] FROM DISK = 'FastWrappers-TSQL.bak'; + GO + + ALTER DATABASE [FastWrappers-TSQL] SET TRUSTWORTHY ON; GO ``` - **Option 2: Deploy DACPAC** - Use SqlPackage or Visual Studio to deploy the .dacpac file. + ### 📖 Documentation + + See [README.md](https://github.com/${{ github.repository }}/blob/main/README.md) for usage examples. - ### Usage + ### ⚠️ Important Notes - See [README.md](https://github.com/${{ github.repository }}/blob/main/README.md) for examples. + - SQL Server 2017+ requires running **Install-TrustedAssembly.sql** first due to CLR strict security + - The assembly is signed and requires UNSAFE permission set + - TRUSTWORTHY ON is required for proper operation files: | release/* draft: false diff --git a/FastWrappers_TSQL.sqlproj b/FastWrappers_TSQL.sqlproj index fba5dd7..e78edfe 100644 --- a/FastWrappers_TSQL.sqlproj +++ b/FastWrappers_TSQL.sqlproj @@ -7,7 +7,7 @@ 2.0 4.1 {4b096d13-154a-472c-9882-f281334958f9} - Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider + Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider Database @@ -32,10 +32,11 @@ AetPCLRSign.pfx.snk True procedures de wrapping pour FastTransfer et FastBCP + 2.0.0.0 - bin\Output\ + bin\Release\ $(MSBuildProjectName).sql False none diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index 697e719..d36e9d6 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -19,5 +19,5 @@ // Numéro de build // Révision // -[assembly: AssemblyVersion("0.5.1.0")] -[assembly: AssemblyFileVersion("0.5.1.0")] +[assembly: AssemblyVersion("0.5.2.0")] +[assembly: AssemblyFileVersion("0.5.2.0")] From 8a937562792b5ee992b263aab03c4243642a7099 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 16:48:18 +0100 Subject: [PATCH 17/37] =?UTF-8?q?Retrait=20des=20modifications=20trusted?= =?UTF-8?q?=20assembly=20-=20retour=20=C3=A0=20v0.5.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 140 ++++------------------------------ Properties/AssemblyInfo.cs | 4 +- 2 files changed, 16 insertions(+), 128 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7eb95b3..1072827 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -90,24 +90,6 @@ jobs: $sqlPackage = "SqlPackage\SqlPackage.exe" - # Calculate SHA2-512 hash of the DLL for trusted assembly - $dllPath = "bin\Output\FastWrappers_TSQL.dll" - Write-Host "Calculating SHA2-512 hash for trusted assembly..." - $dllBytes = [System.IO.File]::ReadAllBytes((Resolve-Path $dllPath).Path) - $sha512 = [System.Security.Cryptography.SHA512]::Create() - $hashBytes = $sha512.ComputeHash($dllBytes) - $hashHex = [System.BitConverter]::ToString($hashBytes).Replace("-", "") - Write-Host "DLL Hash: 0x$hashHex" - - # Add assembly as trusted before deployment (for SQL Server 2017+ with clr strict security) - Write-Host "Adding assembly as trusted..." - $addTrustedAssembly = @" -EXEC sys.sp_add_trusted_assembly - @hash = 0x$hashHex, - @description = N'FastWrappers_TSQL - CLR Wrapper for FastTransfer and FastBCP'; -"@ - sqlcmd -S $serverInstance -Q $addTrustedAssembly - # Deploy the DACPAC to create the database Write-Host "Deploying DACPAC to create database..." & $sqlPackage /Action:Publish /SourceFile:$dacpacPath /TargetServerName:$serverInstance /TargetDatabaseName:$dbName /p:IncludeCompositeObjects=True @@ -137,71 +119,6 @@ EXEC sys.sp_add_trusted_assembly Write-Warning "Failed to create BAK file, continuing..." } - # Generate installation script with trusted assembly setup - Write-Host "Generating installation script with trusted assembly..." - $installScriptPath = "$outputDir\Install-TrustedAssembly.sql" - $installScript = @" --- ============================================= --- FastWrappers-TSQL Installation Script --- For SQL Server 2017+ with CLR Strict Security --- ============================================= --- This script must be run as sysadmin --- ============================================= - -USE master; -GO - --- Check SQL Server version and clr strict security -DECLARE @version INT = CAST(SERVERPROPERTY('ProductMajorVersion') AS INT); -DECLARE @strictSec INT; - -EXEC sp_configure 'show advanced options', 1; -RECONFIGURE; - -SELECT @strictSec = CAST(value_in_use AS INT) -FROM sys.configurations -WHERE name = 'clr strict security'; - -PRINT 'SQL Server Version: ' + CAST(@version AS VARCHAR); -PRINT 'CLR Strict Security: ' + CAST(@strictSec AS VARCHAR); - --- Enable CLR -EXEC sp_configure 'clr enabled', 1; -RECONFIGURE; -GO - --- Add FastWrappers_TSQL as trusted assembly (SQL Server 2017+) --- This allows the assembly to load even with clr strict security enabled -IF NOT EXISTS (SELECT 1 FROM sys.trusted_assemblies WHERE [hash] = 0x$hashHex) -BEGIN - EXEC sys.sp_add_trusted_assembly - @hash = 0x$hashHex, - @description = N'FastWrappers_TSQL, Version=0.5.1.0, Culture=neutral, PublicKeyToken=53f6bd85035abe03'; - PRINT 'Added FastWrappers_TSQL as trusted assembly'; -END -ELSE -BEGIN - PRINT 'FastWrappers_TSQL already in trusted assemblies'; -END -GO - --- Now restore the database or deploy DACPAC --- Example for backup restore: --- RESTORE DATABASE [FastWrappers-TSQL] FROM DISK = 'FastWrappers-TSQL.bak'; --- GO - --- Set TRUSTWORTHY ON (still required for UNSAFE assemblies) --- ALTER DATABASE [FastWrappers-TSQL] SET TRUSTWORTHY ON; --- GO - --- Test --- USE [FastWrappers-TSQL]; --- SELECT dbo.EncryptString('test'); -"@ - - $installScript | Out-File -FilePath $installScriptPath -Encoding UTF8 - Write-Host "Installation script created: $installScriptPath" - # Generate SQL script from DACPAC (includes the compiled binary) Write-Host "Generating SQL script from DACPAC..." & $sqlPackage /Action:Script /SourceFile:$dacpacPath /OutputPath:$generatedSqlPath /p:IncludeCompositeObjects=True @@ -236,8 +153,7 @@ GO @{Source="bin\Release\FastWrappers-TSQL.dacpac"; Name="FastWrappers-TSQL.dacpac"}, @{Source="bin\Release\FastWrappers-TSQL.bacpac"; Name="FastWrappers-TSQL.bacpac"}, @{Source="bin\Release\FastWrappers-TSQL.bak"; Name="FastWrappers-TSQL.bak"}, - @{Source="bin\Release\FastWrappers-TSQL.sql"; Name="FastWrappers-TSQL.sql"}, - @{Source="bin\Release\Install-TrustedAssembly.sql"; Name="Install-TrustedAssembly.sql"} + @{Source="bin\Release\FastWrappers-TSQL.sql"; Name="FastWrappers-TSQL.sql"} ) foreach ($file in $files) { @@ -260,65 +176,37 @@ GO body: | ## FastWrappers-TSQL v${{ steps.get_version.outputs.VERSION }} - ### 📦 Installation Files + ### Installation Files - - **Install-TrustedAssembly.sql** - ⭐ **REQUIRED FIRST** for SQL Server 2017+ (adds assembly to trusted list) - **FastWrappers-TSQL.dacpac** - Data-tier Application Package (for Visual Studio / SQL Server Data Tools) - **FastWrappers-TSQL.bacpac** - Binary Application Package (for import/export between servers) - - **FastWrappers-TSQL.bak** - SQL Server Backup (compatible with SQL Server 2016+, restore using SSMS) + - **FastWrappers-TSQL.bak** - SQL Server Backup (restore using SSMS) - **FastWrappers-TSQL.sql** - SQL Script (execute using sqlcmd or SSMS) - ### 🚀 Installation Instructions + ### Installation - #### For SQL Server 2017+ (with CLR Strict Security) - - **Step 1: Run Install-TrustedAssembly.sql first** (as sysadmin) - ```sql - -- This adds the assembly to sys.trusted_assemblies - -- Run this once per SQL Server instance - sqlcmd -S YourServer -E -i Install-TrustedAssembly.sql - ``` - - **Step 2: Restore database** + **Option 1: Restore from backup (.bak file)** ```sql RESTORE DATABASE [FastWrappers-TSQL] FROM DISK = 'FastWrappers-TSQL.bak'; GO + -- Enable TRUSTWORTHY and CLR ALTER DATABASE [FastWrappers-TSQL] SET TRUSTWORTHY ON; GO - ``` - - **Step 3: Test** - ```sql - USE [FastWrappers-TSQL]; - SELECT dbo.EncryptString('test'); - ``` - #### For SQL Server 2016 or with CLR Strict Security disabled - - ```sql - -- Enable CLR - EXEC sp_configure 'show advanced options', 1; RECONFIGURE; - EXEC sp_configure 'clr enabled', 1; RECONFIGURE; - GO - - -- Restore database - RESTORE DATABASE [FastWrappers-TSQL] FROM DISK = 'FastWrappers-TSQL.bak'; - GO - - ALTER DATABASE [FastWrappers-TSQL] SET TRUSTWORTHY ON; + EXEC sp_configure 'show advanced options', 1; + RECONFIGURE; + EXEC sp_configure 'clr enabled', 1; + RECONFIGURE; GO ``` - ### 📖 Documentation - - See [README.md](https://github.com/${{ github.repository }}/blob/main/README.md) for usage examples. + **Option 2: Deploy DACPAC** + Use SqlPackage or Visual Studio to deploy the .dacpac file. - ### ⚠️ Important Notes + ### Usage - - SQL Server 2017+ requires running **Install-TrustedAssembly.sql** first due to CLR strict security - - The assembly is signed and requires UNSAFE permission set - - TRUSTWORTHY ON is required for proper operation + See [README.md](https://github.com/${{ github.repository }}/blob/main/README.md) for examples. files: | release/* draft: false diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index d36e9d6..697e719 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -19,5 +19,5 @@ // Numéro de build // Révision // -[assembly: AssemblyVersion("0.5.2.0")] -[assembly: AssemblyFileVersion("0.5.2.0")] +[assembly: AssemblyVersion("0.5.1.0")] +[assembly: AssemblyFileVersion("0.5.1.0")] From 2f7ef686b41294497e188e55c2c6a4b59caa5fc4 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 16:49:58 +0100 Subject: [PATCH 18/37] =?UTF-8?q?v0.5.3=20-=20Fix:=20Ajout=20sp=5Fchangedb?= =?UTF-8?q?owner=20'sa'=20pour=20r=C3=A9soudre=20erreur=200x80FC80F1=20ave?= =?UTF-8?q?c=20assemblies=20sign=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 31 ++++++++++++++++++++++++++++++- Properties/AssemblyInfo.cs | 4 ++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1072827..d8a063a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -102,6 +102,18 @@ jobs: # Wait for deployment to complete Start-Sleep -Seconds 5 + # Change database owner to 'sa' (required for signed UNSAFE assemblies to load properly) + Write-Host "Setting database owner to sa..." + sqlcmd -S $serverInstance -d $dbName -Q "EXEC sp_changedbowner 'sa'" + + # Test the assembly + Write-Host "Testing assembly..." + sqlcmd -S $serverInstance -d $dbName -Q "SELECT dbo.EncryptString('test') AS Result" + + if ($LASTEXITCODE -ne 0) { + Write-Warning "Assembly test failed, continuing..." + } + # Export to BACPAC Write-Host "Exporting to BACPAC..." & $sqlPackage /Action:Export /SourceServerName:$serverInstance /SourceDatabaseName:$dbName /TargetFile:$bacpacPath @@ -187,6 +199,7 @@ jobs: **Option 1: Restore from backup (.bak file)** ```sql + -- Restore database RESTORE DATABASE [FastWrappers-TSQL] FROM DISK = 'FastWrappers-TSQL.bak'; GO @@ -199,10 +212,26 @@ jobs: EXEC sp_configure 'clr enabled', 1; RECONFIGURE; GO + + -- IMPORTANT: Change database owner to 'sa' + -- Required for signed UNSAFE assemblies to load properly + USE [FastWrappers-TSQL]; + GO + EXEC sp_changedbowner 'sa'; + GO + + -- Test + SELECT dbo.EncryptString('test'); ``` **Option 2: Deploy DACPAC** - Use SqlPackage or Visual Studio to deploy the .dacpac file. + Use SqlPackage or Visual Studio to deploy the .dacpac file, then run: + ```sql + USE [FastWrappers-TSQL]; + GO + EXEC sp_changedbowner 'sa'; + GO + ``` ### Usage diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index 697e719..6f52ccc 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -19,5 +19,5 @@ // Numéro de build // Révision // -[assembly: AssemblyVersion("0.5.1.0")] -[assembly: AssemblyFileVersion("0.5.1.0")] +[assembly: AssemblyVersion("0.5.3.0")] +[assembly: AssemblyFileVersion("0.5.3.0")] From f18e894eaa408038a9cacb4eaf6e0822c9f37e39 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 17:00:56 +0100 Subject: [PATCH 19/37] =?UTF-8?q?v0.5.4=20-=20Fix:=20Retour=20SQL=20Server?= =?UTF-8?q?=202016=20pour=20compatibilit=C3=A9=20LocalDB=202019?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastWrappers_TSQL.sqlproj | 2 +- Properties/AssemblyInfo.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/FastWrappers_TSQL.sqlproj b/FastWrappers_TSQL.sqlproj index e78edfe..4de4e78 100644 --- a/FastWrappers_TSQL.sqlproj +++ b/FastWrappers_TSQL.sqlproj @@ -7,7 +7,7 @@ 2.0 4.1 {4b096d13-154a-472c-9882-f281334958f9} - Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider + Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider Database diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index 6f52ccc..53fb67a 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -19,5 +19,5 @@ // Numéro de build // Révision // -[assembly: AssemblyVersion("0.5.3.0")] -[assembly: AssemblyFileVersion("0.5.3.0")] +[assembly: AssemblyVersion("0.5.4.0")] +[assembly: AssemblyFileVersion("0.5.4.0")] From aba6c9c353bf033a7d19e6f680205be4bd830031 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Fri, 13 Mar 2026 17:09:35 +0100 Subject: [PATCH 20/37] =?UTF-8?q?v0.5.5=20-=20Fix:=20Activation=20CLR=20av?= =?UTF-8?q?ant=20test=20et=20correction=20g=C3=A9n=C3=A9ration=20script=20?= =?UTF-8?q?SQL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 16 ++++++++++++---- Properties/AssemblyInfo.cs | 4 ++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d8a063a..1d64193 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -106,12 +106,20 @@ jobs: Write-Host "Setting database owner to sa..." sqlcmd -S $serverInstance -d $dbName -Q "EXEC sp_changedbowner 'sa'" + # Enable CLR for testing + Write-Host "Enabling CLR..." + sqlcmd -S $serverInstance -Q "EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'clr enabled', 1; RECONFIGURE;" + # Test the assembly Write-Host "Testing assembly..." - sqlcmd -S $serverInstance -d $dbName -Q "SELECT dbo.EncryptString('test') AS Result" + $testResult = sqlcmd -S $serverInstance -d $dbName -Q "SELECT dbo.EncryptString('test') AS Result" 2>&1 - if ($LASTEXITCODE -ne 0) { - Write-Warning "Assembly test failed, continuing..." + if ($LASTEXITCODE -eq 0) { + Write-Host "Assembly test successful!" + Write-Host $testResult + } else { + Write-Warning "Assembly test failed: $testResult" + Write-Warning "Continuing with artifact creation..." } # Export to BACPAC @@ -133,7 +141,7 @@ jobs: # Generate SQL script from DACPAC (includes the compiled binary) Write-Host "Generating SQL script from DACPAC..." - & $sqlPackage /Action:Script /SourceFile:$dacpacPath /OutputPath:$generatedSqlPath /p:IncludeCompositeObjects=True + & $sqlPackage /Action:Script /SourceFile:$dacpacPath /TargetServerName:$serverInstance /TargetDatabaseName:"${dbName}_Script" /OutputPath:$generatedSqlPath /p:IncludeCompositeObjects=True /p:CommentOutSetVarDeclarations=True if ($LASTEXITCODE -ne 0) { Write-Warning "Failed to generate SQL script, continuing..." diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index 53fb67a..8502289 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -19,5 +19,5 @@ // Numéro de build // Révision // -[assembly: AssemblyVersion("0.5.4.0")] -[assembly: AssemblyFileVersion("0.5.4.0")] +[assembly: AssemblyVersion("0.5.5.0")] +[assembly: AssemblyFileVersion("0.5.5.0")] From b13dae514a1c1814f93a6788f141f17bd99d62f6 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Mon, 16 Mar 2026 08:31:39 +0100 Subject: [PATCH 21/37] =?UTF-8?q?v0.6.0=20-=20Ajout=20des=20param=C3=A8tre?= =?UTF-8?q?s=20FastTransfer=20v0.15:=20useWorkTables,=20dataDrivenQuery,?= =?UTF-8?q?=20noBanner,=20Physloc,=20NZDataSlice?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastTransferWrapper_SP.cs | 77 +++++++++++++++++++++++++------------- Properties/AssemblyInfo.cs | 4 +- 2 files changed, 52 insertions(+), 29 deletions(-) diff --git a/FastTransferWrapper_SP.cs b/FastTransferWrapper_SP.cs index 3dacc91..9079499 100644 --- a/FastTransferWrapper_SP.cs +++ b/FastTransferWrapper_SP.cs @@ -69,10 +69,12 @@ public static void RunFastTransfer_Secure( SqlString targetTable, SqlString loadMode, SqlInt32 batchSize, + SqlBoolean useWorkTables, // 6) Advanced SqlString method, SqlString distributeKeyColumn, + SqlString dataDrivenQuery, SqlInt32 degree, SqlString mapMethod, @@ -80,6 +82,7 @@ public static void RunFastTransfer_Secure( SqlString runId, SqlString settingsFile, SqlBoolean debug, + SqlBoolean noBanner, // 8) License (optional, can be null or empty if not required SqlString license, @@ -148,13 +151,16 @@ SqlString loglevel targetTable, loadMode, batchSize, + useWorkTables, method, distributeKeyColumn, + dataDrivenQuery, degree, mapMethod, runId, settingsFile, debug, + noBanner, license, loglevel ); @@ -186,13 +192,16 @@ private static void RunFastTransferInternal( SqlString targetTable, // Mandatory. eg "CopyTable" SqlString loadMode, // "Append" or "Truncate" SqlInt32 batchSize, // e.g. 130000 - SqlString method, // distribution method for parallelism :"None", "Random", "DataDriven", "RangeId", "Ntile", "Ctid", "Rowid" + SqlBoolean useWorkTables, // use staging work tables before final insert + SqlString method, // distribution method for parallelism :"None", "Random", "DataDriven", "RangeId", "Ntile", "Ctid", "Rowid", "Physloc", "NZDataSlice" SqlString distributeKeyColumn, // required if method in ["Random","DataDriven","RangeId","Ntile"] + SqlString dataDrivenQuery, // custom query for DataDriven method returning distinct values for distribution SqlInt32 degree, // concurrency degree if method != "None" useless if method = "None" should be != 1, can be less than 0 for dynamic degree (based on cpucount on the platform where FastTransfer is running. -2 = CpuCount/2) SqlString mapMethod, // "Position"(default) or "Name" (Automatic mapping of columns based on names (case insensitive) with tolerance on the order of columns. Non present columns in source or target are ignored. Name may mot be available for all target types (see doc)) SqlString runId, // a run identifier for logging (can be a string for grouping or a unique identifier). Guid is used if not provide SqlString settingsFile, // path for a custom FastTransfer_Settings.json file, for custom logging SqlBoolean debug, // for debugging purpose, if true, the FastTransfer_Settings.json file is created in the current directory with the default settings + SqlBoolean noBanner, // suppress FastTransfer banner and version information at startup SqlString license, // license key file or url for FastTransfer (optional, can be null or empty if not required) SqlString loglevel // optional, can be "error", "warning", "information", "debug" (default is "information") ) @@ -231,17 +240,20 @@ private static void RunFastTransferInternal( string tgtTableVal = targetTable.IsNull ? null : targetTable.Value.Trim(); string loadModeVal = loadMode.IsNull ? null : loadMode.Value.Trim(); int? batchSizeVal = batchSize.IsNull ? (int?)null : batchSize.Value; + bool useWorkTablesVal = !useWorkTables.IsNull && useWorkTables.Value; - string methodVal = method.IsNull ? null : method.Value.Trim(); - string distKeyColVal = distributeKeyColumn.IsNull ? null : distributeKeyColumn.Value.Trim(); - int? degreeVal = degree.IsNull ? (int?)null : degree.Value; - string mapMethodVal = mapMethod.IsNull ? null : mapMethod.Value.Trim(); + string methodVal = method.IsNull ? null : method.Value.Trim(); + string distKeyColVal = distributeKeyColumn.IsNull ? null : distributeKeyColumn.Value.Trim(); + string dataDrivenQueryVal = dataDrivenQuery.IsNull ? null : dataDrivenQuery.Value.Trim(); + int? degreeVal = degree.IsNull ? (int?)null : degree.Value; + string mapMethodVal = mapMethod.IsNull ? null : mapMethod.Value.Trim(); - string runIdVal = runId.IsNull ? null : runId.Value.Trim(); - string settingsFileVal = settingsFile.IsNull ? null : settingsFile.Value.Trim(); + string runIdVal = runId.IsNull ? null : runId.Value.Trim(); + string settingsFileVal = settingsFile.IsNull ? null : settingsFile.Value.Trim(); - bool debugVal = !debug.IsNull && debug.Value ? true : false; - // If license is provided, it can be null or empty if not required + bool debugVal = !debug.IsNull && debug.Value ? true : false; + bool noBannerVal = !noBanner.IsNull && noBanner.Value; + // If license is provided, it can be null or empty if not required string licenseVal = license.IsNull ? null : license.Value.Trim(); // Default loglevel to "information" @@ -382,10 +394,10 @@ private static void RunFastTransferInternal( bool hasMethod = !string.IsNullOrEmpty(methodVal); if (hasMethod) { - string[] validMethods = { "None", "Random", "DataDriven", "RangeId", "Ntile", "Ctid", "Rowid" , "NZDataSlice" }; + string[] validMethods = { "None", "Random", "DataDriven", "RangeId", "Ntile", "Ctid", "Rowid", "Physloc", "NZDataSlice" }; if (Array.IndexOf(validMethods, methodVal) < 0) { - throw new ArgumentException($"Invalid method: '{methodVal}'. use 'None', 'Random', 'DataDriven', 'RangeId', 'Ntile', 'NZDataSlice', 'Ctid' or 'Rowid'. WARNING the parameter is Case Sensitive"); + throw new ArgumentException($"Invalid method: '{methodVal}'. use 'None', 'Random', 'DataDriven', 'RangeId', 'Ntile', 'Ctid', 'Rowid', 'Physloc' or 'NZDataSlice'. WARNING the parameter is Case Sensitive"); } if (!methodVal.Equals("None")) @@ -551,6 +563,10 @@ private static void RunFastTransferInternal( { args += $" --batchsize {batchSizeVal.Value}"; } + if (useWorkTablesVal) + { + args += " --useworktables"; + } // Advanced Parameters if (hasMethod) @@ -571,24 +587,27 @@ private static void RunFastTransferInternal( args += $" --degree {degreeVal.Value}"; } } - if (hasMapMethod) - { - args += $" --mapmethod {Q(mapMethodVal)}"; - } + if (!string.IsNullOrEmpty(dataDrivenQueryVal)) + { + args += $" --datadrivenquery {Q(dataDrivenQueryVal)}"; + } + if (hasMapMethod) + { + args += $" --mapmethod {Q(mapMethodVal)}"; + } - // Log Parameters - if (!string.IsNullOrEmpty(runIdVal)) - { - args += $" --runid {Q(runIdVal)}"; - } - if (!string.IsNullOrEmpty(settingsFileVal)) - { - args += $" --settingsfile {Q(settingsFileVal)}"; - } + // Log Parameters + if (!string.IsNullOrEmpty(runIdVal)) + { + args += $" --runid {Q(runIdVal)}"; + } + if (!string.IsNullOrEmpty(settingsFileVal)) + { + args += $" --settingsfile {Q(settingsFileVal)}"; + } - // License (optional) - if (!string.IsNullOrEmpty(licenseVal)) - { + // License (optional) + if (!string.IsNullOrEmpty(licenseVal)) args += $" --license {Q(licenseVal)}"; } @@ -597,6 +616,10 @@ private static void RunFastTransferInternal( { args += $" --loglevel {Q(loglevelVal)}"; } + if (noBannerVal) + { + args += " --nobanner"; + } // Trim leading space args = args.Trim(); diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index 8502289..29b7b18 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -19,5 +19,5 @@ // Numéro de build // Révision // -[assembly: AssemblyVersion("0.5.5.0")] -[assembly: AssemblyFileVersion("0.5.5.0")] +[assembly: AssemblyVersion("0.6.0.0")] +[assembly: AssemblyFileVersion("0.6.0.0")] From 50147bee3b3997abc1841215d74049669005f78a Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Mon, 16 Mar 2026 08:35:19 +0100 Subject: [PATCH 22/37] Fix: correction erreur syntaxe accolade manquante ligne 611 --- FastTransferWrapper_SP.cs | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/FastTransferWrapper_SP.cs b/FastTransferWrapper_SP.cs index 9079499..67ddc5a 100644 --- a/FastTransferWrapper_SP.cs +++ b/FastTransferWrapper_SP.cs @@ -608,28 +608,22 @@ private static void RunFastTransferInternal( // License (optional) if (!string.IsNullOrEmpty(licenseVal)) - args += $" --license {Q(licenseVal)}"; - } - - // Loglevel - if (!string.IsNullOrEmpty(loglevelVal)) - { - args += $" --loglevel {Q(loglevelVal)}"; - } - if (noBannerVal) - { - args += " --nobanner"; - } + { + args += $" --license {Q(licenseVal)}"; + } - // Trim leading space - args = args.Trim(); + // Loglevel + if (!string.IsNullOrEmpty(loglevelVal)) + { + args += $" --loglevel {Q(loglevelVal)}"; + } + if (noBannerVal) + { + args += " --nobanner"; + } - //args4Log : for logging purpose, remove password or passwd info in the args string using regexp - string args4Log = args; - args4Log = System.Text.RegularExpressions.Regex.Replace(args4Log, @"--sourcepassword\s+""[^""]*""", "--sourcepassword \"\""); - args4Log = System.Text.RegularExpressions.Regex.Replace(args4Log, @"--targetpassword\s+""[^""]*""", "--targetpassword \"\""); - args4Log = System.Text.RegularExpressions.Regex.Replace(args4Log, @"--sourceconnectstring\s+""[^""]*""", "--sourceconnectstring \"\""); - args4Log = System.Text.RegularExpressions.Regex.Replace(args4Log, @"--targetconnectstring\s+""[^""]*""", "--targetconnectstring \"\""); + // Trim leading space + args = args.Trim(); if (debugVal) From a822379e88e4d58e6e692f33e0276f0622f49964 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Mon, 16 Mar 2026 08:38:31 +0100 Subject: [PATCH 23/37] =?UTF-8?q?Fix:=20ajout=20d=C3=A9claration=20args4Lo?= =?UTF-8?q?g=20manquante?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastTransferWrapper_SP.cs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/FastTransferWrapper_SP.cs b/FastTransferWrapper_SP.cs index 67ddc5a..1cfccc8 100644 --- a/FastTransferWrapper_SP.cs +++ b/FastTransferWrapper_SP.cs @@ -625,15 +625,18 @@ private static void RunFastTransferInternal( // Trim leading space args = args.Trim(); - - if (debugVal) - { - //print the command line exe and args - SqlContext.Pipe.Send("FastTransfer Command " + exePath + " " + args4Log + Environment.NewLine); - } - - // -------------------------------------------------------------------- - // 4. Execute the CLI + //args4Log : for logging purpose, remove password or passwd info in the args string using regexp + string args4Log = args; + args4Log = System.Text.RegularExpressions.Regex.Replace(args4Log, @"--sourcepassword\s+""[^""]*""", "--sourcepassword \"\""); + args4Log = System.Text.RegularExpressions.Regex.Replace(args4Log, @"--targetpassword\s+""[^""]*""", "--targetpassword \"\""); + args4Log = System.Text.RegularExpressions.Regex.Replace(args4Log, @"--sourceconnectstring\s+""[^""]*""", "--sourceconnectstring \"\""); + args4Log = System.Text.RegularExpressions.Regex.Replace(args4Log, @"--targetconnectstring\s+""[^""]*""", "--targetconnectstring \"\""); + + if (debugVal) + { + //print the command line exe and args + SqlContext.Pipe.Send("FastTransfer Command " + exePath + " " + args4Log + Environment.NewLine); + } // -------------------------------------------------------------------- ProcessStartInfo psi = new ProcessStartInfo { From 5c6cf9d40e3d2e97f5687c7a3158b112938aec21 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Mon, 16 Mar 2026 08:40:54 +0100 Subject: [PATCH 24/37] =?UTF-8?q?Fix:=20mise=20=C3=A0=20jour=20signature?= =?UTF-8?q?=20SQL=20avec=20nouveaux=20param=C3=A8tres=20v0.6.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- xp_RunFastTransfer_secure.sql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xp_RunFastTransfer_secure.sql b/xp_RunFastTransfer_secure.sql index 6e0ed39..172a3ea 100644 --- a/xp_RunFastTransfer_secure.sql +++ b/xp_RunFastTransfer_secure.sql @@ -55,13 +55,16 @@ CREATE PROCEDURE [dbo].[xp_RunFastTransfer_secure] @targetTable [nvarchar](255), @loadMode [nvarchar](50), @batchSize [int] = 1048576, + @useWorkTables [bit] = 0, @method [nvarchar](50) = 'None', @distributeKeyColumn [nvarchar](255) = NULL, + @dataDrivenQuery [nvarchar](4000) = NULL, @degree [int] = 4, @mapmethod [nvarchar](50) = 'Position', @runId [nvarchar](255) = NULL, @settingsFile [nvarchar](4000) = NULL, @debug [bit] = 0, + @noBanner [bit] = 0, @license nvarchar(4000) = NULL, @loglevel nvarchar(50) = 'information' WITH EXECUTE AS CALLER From 43d8c5b6ff5603963362c038f76537a3fb1a57a0 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Mon, 16 Mar 2026 09:07:36 +0100 Subject: [PATCH 25/37] =?UTF-8?q?v0.7.0=20-=20Ajout=20param=C3=A8tres=20Fa?= =?UTF-8?q?stBCP:=20applicationintent,=20parquetcompression,=20config,=20n?= =?UTF-8?q?obanner=20+=20m=C3=A9thode=20Timepartition?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastBCPWrapper_SP.cs.cs | 25 ++++++++++++++++++++++++- Properties/AssemblyInfo.cs | 4 ++-- xp_RunFastBCP_secure.sql | 4 ++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/FastBCPWrapper_SP.cs.cs b/FastBCPWrapper_SP.cs.cs index eae5fca..03b6995 100644 --- a/FastBCPWrapper_SP.cs.cs +++ b/FastBCPWrapper_SP.cs.cs @@ -26,6 +26,7 @@ public static void RunFastBCP_Secure( SqlString sourcepasswordEnc, // chiffré (Base64) ; exclusif avec Trusted SqlBoolean trusted, // exclusif avec User/Password SqlString sourcedatabase, // obligatoire si pas de connectstring + SqlString applicationintent, // ReadOnly (default) | ReadWrite (SQL Server & OLEDB only) // Sources infos SqlString inputFile, // -F fileinput (optionnel) – exclusif avec query @@ -43,10 +44,11 @@ public static void RunFastBCP_Secure( SqlString dateformat, // -f (default "yyyy-MM-dd") SqlString encoding, // -e (default "UTF-8") SqlString decimalseparator, // -n (default ",") + SqlString parquetcompression, // zstd;none;snappy;gzip;lzo;lz4 (default zstd) // Parallel options SqlInt32 degree, // -p (Default -2) - SqlString method, // -m (Random;DataDriven;Ctid;Physloc;Rowid;RangeId;Ntile;None) (Default None) + SqlString method, // -m (Random;DataDriven;Ctid;Physloc;Rowid;RangeId;Ntile;Timepartition;None) (Default None) SqlString distributeKeyColumn, // -c SqlString datadrivenquery, // -Q (optionnel) SqlBoolean mergeDistributedFile, // -M (bool) default True @@ -57,9 +59,11 @@ public static void RunFastBCP_Secure( SqlString boolformat, // -b automatic;true/false;1/0;t/f; SqlString runid, // -R SqlString settingsfile, // -l (default FastBCP_Settings.json) + SqlString config, // --config (YAML config file) SqlString cloudprofile, // --cloudprofile SqlString license, // --license | --licence SqlString loglevel, // --loglevel Information|Debug|Verbose + SqlBoolean nobanner, // --nobanner (suppress banner) SqlBoolean debug // --debug (output stdout to SQL client) ) { @@ -88,6 +92,7 @@ public static void RunFastBCP_Secure( bool trustedVal = !trusted.IsNull && trusted.Value; string databaseVal = sourcedatabase.IsNull ? null : sourcedatabase.Value.Trim(); + string applicationintentVal = applicationintent.IsNull ? null : applicationintent.Value.Trim(); string inputFileVal = inputFile.IsNull ? null : inputFile.Value.Trim(); string queryVal = query.IsNull ? null : query.Value.Trim(); @@ -102,6 +107,7 @@ public static void RunFastBCP_Secure( string datefmtVal = dateformat.IsNull ? null : dateformat.Value.Trim(); string encodingVal = encoding.IsNull ? null : encoding.Value.Trim(); string decSepVal = decimalseparator.IsNull ? null : decimalseparator.Value.Trim(); + string parquetcompressionVal = parquetcompression.IsNull ? null : parquetcompression.Value.Trim(); int? degreeVal = degree.IsNull ? (int?)null : degree.Value; string methodVal = method.IsNull ? null : method.Value.Trim(); @@ -114,9 +120,11 @@ public static void RunFastBCP_Secure( string boolfmtVal = boolformat.IsNull ? null : boolformat.Value.Trim(); string runidVal = runid.IsNull ? null : runid.Value.Trim(); string settingsVal = settingsfile.IsNull ? null : settingsfile.Value.Trim(); + string configVal = config.IsNull ? null : config.Value.Trim(); string cloudProfVal = cloudprofile.IsNull ? null : cloudprofile.Value.Trim(); string licenseVal = license.IsNull ? null : license.Value.Trim(); string loglevelVal = loglevel.IsNull ? null : loglevel.Value.Trim(); + bool nobannerVal = !nobanner.IsNull && nobanner.Value; bool debugVal = !debug.IsNull && debug.Value ? true : false; // ----------------------------- @@ -226,6 +234,13 @@ public static void RunFastBCP_Secure( args.Append(" --sourcedatabase ").Append(Q(databaseVal)); } + // application intent (SQL Server & OLEDB only) + if (!string.IsNullOrEmpty(applicationintentVal) && + (connType == "mssql" || connType == "oledb" || connType == "msoledbsql")) + { + args.Append(" --applicationintent ").Append(applicationintentVal); + } + // decimal separator if (!string.IsNullOrEmpty(decSepVal)) args.Append(" --decimalseparator ").Append(Q(decSepVal)); @@ -253,6 +268,10 @@ public static void RunFastBCP_Secure( if (!string.IsNullOrEmpty(encodingVal)) args.Append(" --encoding ").Append(Q(encodingVal)); + // parquet compression + if (!string.IsNullOrEmpty(parquetcompressionVal)) + args.Append(" --parquetcompression ").Append(Q(parquetcompressionVal)); + // Parallel options if (degreeVal.HasValue) args.Append(" --paralleldegree ").Append(degreeVal.Value); @@ -274,12 +293,16 @@ public static void RunFastBCP_Secure( args.Append(" --runid ").Append(Q(runidVal)); if (!string.IsNullOrEmpty(settingsVal)) args.Append(" --settingsfile ").Append(Q(settingsVal)); + if (!string.IsNullOrEmpty(configVal)) + args.Append(" --config ").Append(Q(configVal)); if (!string.IsNullOrEmpty(cloudProfVal)) args.Append(" --cloudprofile ").Append(Q(cloudProfVal)); if (!string.IsNullOrEmpty(licenseVal)) args.Append(" --license ").Append(Q(licenseVal)); if (!string.IsNullOrEmpty(loglevelVal)) args.Append(" --loglevel ").Append(Q(loglevelVal)); + if (nobannerVal) + args.Append(" --nobanner"); string argLine = args.ToString().Trim(); diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index 29b7b18..843001f 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -19,5 +19,5 @@ // Numéro de build // Révision // -[assembly: AssemblyVersion("0.6.0.0")] -[assembly: AssemblyFileVersion("0.6.0.0")] +[assembly: AssemblyVersion("0.7.0.0")] +[assembly: AssemblyFileVersion("0.7.0.0")] diff --git a/xp_RunFastBCP_secure.sql b/xp_RunFastBCP_secure.sql index b6c9279..36f106b 100644 --- a/xp_RunFastBCP_secure.sql +++ b/xp_RunFastBCP_secure.sql @@ -86,6 +86,7 @@ CREATE PROCEDURE [dbo].[xp_RunFastBCP_secure] @sourcepasswordSecure [nvarchar](255) = NULL, @isTrusted [bit] = 0, @sourcedatabase [nvarchar](1000), +@applicationintent [nvarchar](20) = 'ReadOnly', @inputFile [nvarchar](1000) = NULL, @query [nvarchar](4000) = NULL, @sourceschema [nvarchar](255) = NULL, @@ -97,6 +98,7 @@ CREATE PROCEDURE [dbo].[xp_RunFastBCP_secure] @dateformat [nvarchar](25) = NULL, @encoding [nvarchar](50) = NULL, @decimalSeparator [nvarchar](1) = NULL, +@parquetcompression [nvarchar](20) = 'zstd', @degree [int] = -2, @method [nvarchar](50) = 'None', @distributeKeyColumn [nvarchar](1000) = NULL, @@ -107,9 +109,11 @@ CREATE PROCEDURE [dbo].[xp_RunFastBCP_secure] @boolformat [nvarchar](10) = NULL, @runid [nvarchar](255) = NULL, @settingsfile [nvarchar](4000) = NULL, +@config [nvarchar](4000) = NULL, @cloudprofile [nvarchar](2000) = NULL, @license nvarchar(4000) = NULL, @loglevel nvarchar(50) = 'Information', +@nobanner [bit] = 0, @debug [bit] = 0 WITH EXECUTE AS CALLER AS From 3fe229211ec47a1f18b8544b4eeea5d0a3d49ce5 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Mon, 16 Mar 2026 09:17:44 +0100 Subject: [PATCH 26/37] docs: ajout instructions configuration post-installation (TRUSTWORTHY, CLR, db owner) --- README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/README.md b/README.md index b65177d..13b046a 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,32 @@ Download the latest release from the [Releases page](https://github.com/aetperf/ 3. **FastWrappers-TSQL.bak** - SQL Server Backup file (compatible with SQL Server 2016+, restore using SSMS) 4. **FastWrappers-TSQL.sql** - Pure SQL Script (execute using sqlcmd or SSMS) +### Post-Installation Configuration + +After restoring the database (especially from .bak), you **must** run the following commands to enable CLR and configure the database properly: + +```sql +-- Enable TRUSTWORTHY for signed UNSAFE assemblies +ALTER DATABASE [FastWrappers-TSQL] SET TRUSTWORTHY ON; +GO + +-- Enable advanced options +EXEC sp_configure 'show advanced options', 1; +RECONFIGURE; +GO + +-- Enable CLR integration +EXEC sp_configure 'clr enabled', 1; +RECONFIGURE; +GO + +-- Set database owner to 'sa' (required for signed UNSAFE assemblies) +EXEC sp_changedbowner 'sa'; +GO +``` + +**Important:** The `sp_changedbowner 'sa'` command is **critical** for signed UNSAFE CLR assemblies to work. Without it, you will encounter error 0x80FC80F1 when trying to execute the stored procedures. + ## Creating a New Release To create a new release: From df5b0e48790694d5d10d44d02283e899728179b2 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Mon, 16 Mar 2026 09:40:26 +0100 Subject: [PATCH 27/37] docs: suppression section Creating a New Release --- README.md | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/README.md b/README.md index 13b046a..bf91373 100644 --- a/README.md +++ b/README.md @@ -40,20 +40,7 @@ GO **Important:** The `sp_changedbowner 'sa'` command is **critical** for signed UNSAFE CLR assemblies to work. Without it, you will encounter error 0x80FC80F1 when trying to execute the stored procedures. -## Creating a New Release - -To create a new release: - -1. Update the version number in [Properties/AssemblyInfo.cs](Properties/AssemblyInfo.cs) -2. Commit your changes -3. Create and push a new tag: - ```bash - git tag v0.3.3 - git push origin v0.3.3 - ``` -4. The GitHub Actions workflow will automatically build and create a release with all installation artifacts - -Samples usage : +## Usage Examples ### Copy one table using 12 threads between two MSSQL instances ```TSQL From e8627e12291c6aedf6d1a13c4fa5b4aa6e76a601 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Mon, 16 Mar 2026 09:46:29 +0100 Subject: [PATCH 28/37] =?UTF-8?q?docs:=20ajout=20option=20sp=5Fadd=5Ftrust?= =?UTF-8?q?ed=5Fassembly=20(s=C3=A9curis=C3=A9e)=20pour=20configuration=20?= =?UTF-8?q?post-installation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index bf91373..0bf0d2a 100644 --- a/README.md +++ b/README.md @@ -16,19 +16,65 @@ Download the latest release from the [Releases page](https://github.com/aetperf/ ### Post-Installation Configuration -After restoring the database (especially from .bak), you **must** run the following commands to enable CLR and configure the database properly: +After restoring the database (especially from .bak), you **must** configure CLR integration. Two options are available depending on your environment: + +#### Option 1: Using sp_add_trusted_assembly (Recommended for Production) 🔒 + +This approach is **more secure** as it keeps TRUSTWORTHY OFF and doesn't require changing the database owner: + +```sql +-- Enable CLR integration +EXEC sp_configure 'show advanced options', 1; +RECONFIGURE; +GO + +EXEC sp_configure 'clr enabled', 1; +RECONFIGURE; +GO + +-- Extract the assembly hash and add it to trusted assemblies +DECLARE @hash VARBINARY(64); + +SELECT @hash = HASHBYTES('SHA2_512', content) +FROM sys.assembly_files +WHERE assembly_id = ( + SELECT assembly_id + FROM sys.assemblies + WHERE name = 'FastWrappers_TSQL' +); + +EXEC sys.sp_add_trusted_assembly + @hash = @hash, + @description = N'FastWrappers_TSQL Assembly v0.7.0'; +GO +``` + +**Advantages:** +- ✅ TRUSTWORTHY remains OFF (more secure) +- ✅ No need to change database owner +- ✅ Only this specific assembly is trusted + +**Note:** The assembly hash changes with each version. When upgrading, you must remove the old hash and add the new one: +```sql +-- Remove old version +EXEC sys.sp_drop_trusted_assembly @hash = ; +-- Then run the sp_add_trusted_assembly script above +``` + +#### Option 2: Using TRUSTWORTHY ON (Quick Setup for Dev/Test) + +This approach is simpler but **less secure**. Use only for development/testing environments: ```sql -- Enable TRUSTWORTHY for signed UNSAFE assemblies ALTER DATABASE [FastWrappers-TSQL] SET TRUSTWORTHY ON; GO --- Enable advanced options +-- Enable CLR integration EXEC sp_configure 'show advanced options', 1; RECONFIGURE; GO --- Enable CLR integration EXEC sp_configure 'clr enabled', 1; RECONFIGURE; GO @@ -38,7 +84,7 @@ EXEC sp_changedbowner 'sa'; GO ``` -**Important:** The `sp_changedbowner 'sa'` command is **critical** for signed UNSAFE CLR assemblies to work. Without it, you will encounter error 0x80FC80F1 when trying to execute the stored procedures. +**Important:** With this method, the `sp_changedbowner 'sa'` command is **critical**. Without it, you will encounter error 0x80FC80F1 when trying to execute the stored procedures. ## Usage Examples From c4ab02b84b078677a7276999c19d86d8a7994459 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Mon, 16 Mar 2026 09:51:38 +0100 Subject: [PATCH 29/37] =?UTF-8?q?docs:=20ajout=20section=20'Available=20St?= =?UTF-8?q?ored=20Procedures'=20d=C3=A9crivant=20le=20contenu=20du=20wrapp?= =?UTF-8?q?er?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0bf0d2a..3a87afb 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Download the latest release from the [Releases page](https://github.com/aetperf/ After restoring the database (especially from .bak), you **must** configure CLR integration. Two options are available depending on your environment: -#### Option 1: Using sp_add_trusted_assembly (Recommended for Production) 🔒 +#### Option 1: Using sp_add_trusted_assembly (Recommended for Production) This approach is **more secure** as it keeps TRUSTWORTHY OFF and doesn't require changing the database owner: @@ -86,6 +86,53 @@ GO **Important:** With this method, the `sp_changedbowner 'sa'` command is **critical**. Without it, you will encounter error 0x80FC80F1 when trying to execute the stored procedures. +## Available Stored Procedures + +Once installed and configured, the FastWrappers-TSQL assembly provides the following stored procedures: + +### 1. **dbo.EncryptString** - Password Encryption Function +```sql +SELECT dbo.EncryptString('YourPassword') +``` +Encrypts passwords using AES-256 encryption. Use this function to generate encrypted passwords for the `@sourcePasswordSecure` and `@targetPasswordSecure` parameters. + +**Returns:** Base64-encoded encrypted string + +### 2. **dbo.xp_RunFastTransfer_secure** - Data Transfer Wrapper +```sql +EXEC dbo.xp_RunFastTransfer_secure @fastTransferDir = '...', ... +``` +Wraps the **FastTransfer** CLI to transfer data between databases with streaming and parallel processing for high performance. + +**Key Features:** +- Supports 13 source connection types (ClickHouse, DuckDB, HANA, SQL Server, MySQL, Netezza, Oracle, PostgreSQL, Teradata, ODBC, OLEDB) +- Supports 10 target connection types with bulk loading (clickhousebulk, duckdb, hanabulk, msbulk, mysqlbulk, nzbulk, orabulk, oradirect, pgcopy, teradata) +- Parallel methods: None, Random, DataDriven, RangeId, Ntile, Ctid (PostgreSQL), Physloc (SQL Server), Rowid (Oracle), NZDataSlice (Netezza) +- Automatic column mapping by position or name +- Encrypted connection strings and passwords using AES-256 +- Configurable batch sizes and parallelism degree +- Load modes: Append, Truncate +- Work tables support for staging data +- Custom data-driven distribution queries + +### 3. **dbo.xp_RunFastBCP_secure** - Data Export Wrapper +```sql +EXEC dbo.xp_RunFastBCP_secure @fastBCPDir = '...', ... +``` +Wraps the **FastBCP** CLI to export data from databases to files with streaming and parallel processing for high performance. + +**Key Features:** +- Supports 11 connection types (ClickHouse, HANA, SQL Server, MySQL, Netezza, ODBC, OLEDB, Oracle, PostgreSQL, Teradata) +- Multiple output formats: CSV, TSV, JSON, Parquet, BSON, Binary (PostgreSQL COPY), XLSX (Excel) +- Parquet compression codecs: Zstd (default), Snappy, Gzip, Lzo, Lz4, None +- Parallel methods: None, Random, DataDriven, RangeId, Ntile, Timepartition, Ctid (PostgreSQL), Physloc (SQL Server), Rowid (Oracle) +- Cloud storage support: AWS S3, Azure Blob Storage, Azure Data Lake Gen2, Google Cloud Storage, S3-Compatible, OneLake +- Configurable CSV/TSV formatting (delimiter, quotes, date format, decimal separator, boolean format, encoding) +- Encrypted connection strings and passwords using AES-256 +- File merge option for parallel exports +- Timestamped output files +- YAML configuration file support + ## Usage Examples ### Copy one table using 12 threads between two MSSQL instances From b79b595da8593a8995cdee102c55211585640032 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Mon, 16 Mar 2026 10:07:32 +0100 Subject: [PATCH 30/37] docs: ajout section 'Logging and Output' pour FastTransfer avec description debug mode --- README.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/README.md b/README.md index 3a87afb..bcb6bdb 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,55 @@ Wraps the **FastBCP** CLI to export data from databases to files with streaming - Timestamped output files - YAML configuration file support +## Logging and Output + +### FastTransfer Output + +By default, **xp_RunFastTransfer_secure** returns a structured result set with transfer metrics: + +| Column | Type | Description | +|--------|------|-------------| +| targetdatabase | nvarchar(128) | Target database name | +| targetSchema | nvarchar(128) | Target schema name | +| targetTable | nvarchar(128) | Target table name | +| TotalRows | bigint | Number of rows transferred | +| TotalColumns | int | Number of columns transferred | +| TotalCells | bigint | Total cells transferred (rows × columns) | +| TotalTimeMs | bigint | Total execution time in milliseconds | +| Status | int | Exit code (0 = success, non-zero = error) | +| StdErr | nvarchar(max) | Error message if Status ≠ 0 | + +**Example output:** +``` +targetdatabase targetSchema targetTable TotalRows TotalColumns TotalCells TotalTimeMs Status StdErr +postgres public orders 15000000 9 135000000 27502 0 +``` + +#### Debug Mode (@debug = 1) + +When you set `@debug = 1`, the stored procedure will also output: + +1. **The complete command line** being executed (in the Messages tab): + ``` + FastTransfer Command .\FastTransfer.exe --sourceconnectiontype "mssql" --sourceserver "localhost" ... + ``` + *(Passwords and connection strings are automatically masked with `` for security)* + +2. **The full console output (stdout)** from FastTransfer (in the Messages tab): + - Real-time progress updates + - Detailed execution logs + - Performance metrics + - Any warnings or informational messages + +**Example with debug:** +```sql +EXEC dbo.xp_RunFastTransfer_secure + @fastTransferDir = 'C:\FastTransfer\latest', + @sourceConnectionType = 'mssql', + -- ... other parameters ... + @debug = 1 -- Enable verbose logging +``` + ## Usage Examples ### Copy one table using 12 threads between two MSSQL instances From 9297b78e7888f98d7d76cfdfabe1bb1422a1414a Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Mon, 16 Mar 2026 10:59:07 +0100 Subject: [PATCH 31/37] =?UTF-8?q?docs:=20ajout=20section=20'Security=20Rol?= =?UTF-8?q?es'=20d=C3=A9taillant=20FastTransfer=5FExecutor=20et=20FastBCP?= =?UTF-8?q?=5FExecutor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/README.md b/README.md index bcb6bdb..d9febe0 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,54 @@ GO **Important:** With this method, the `sp_changedbowner 'sa'` command is **critical**. Without it, you will encounter error 0x80FC80F1 when trying to execute the stored procedures. +## Security Roles + +The FastWrappers-TSQL database includes two predefined database roles to manage access to the stored procedures: + +### 1. **FastTransfer_Executor** + +This role grants `EXECUTE` permission on the **xp_RunFastTransfer_secure** stored procedure. + +**Usage:** +```sql +-- Add a user to the FastTransfer_Executor role +ALTER ROLE [FastTransfer_Executor] ADD MEMBER [YourUserName]; +GO +``` + +**Purpose:** Allows users to perform data transfers between databases without granting them broader permissions. + +### 2. **FastBCP_Executor** + +This role grants `EXECUTE` permission on the **xp_RunFastBCP_secure** stored procedure. + +**Usage:** +```sql +-- Add a user to the FastBCP_Executor role +ALTER ROLE [FastBCP_Executor] ADD MEMBER [YourUserName]; +GO +``` + +**Purpose:** Allows users to export data to files without granting them broader permissions. + +### Combined Access + +To grant a user access to both FastTransfer and FastBCP: + +```sql +-- Add user to both roles +ALTER ROLE [FastTransfer_Executor] ADD MEMBER [YourUserName]; +ALTER ROLE [FastBCP_Executor] ADD MEMBER [YourUserName]; +GO +``` + +**Note:** Users also need access to the **dbo.EncryptString** function to generate encrypted passwords. Consider granting `EXECUTE` permission explicitly if needed: + +```sql +GRANT EXECUTE ON dbo.EncryptString TO [YourUserName]; +GO +``` + ## Available Stored Procedures Once installed and configured, the FastWrappers-TSQL assembly provides the following stored procedures: From f4db21d96b47747972fa1fb4ea1d4aff72bb98f7 Mon Sep 17 00:00:00 2001 From: Romain Ferraton <16419423+rferraton@users.noreply.github.com> Date: Wed, 18 Mar 2026 00:04:21 +0100 Subject: [PATCH 32/37] Potential fix for pull request finding more generic version numer Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .github/workflows/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 27c7ac9..35659c6 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -4,7 +4,7 @@ This GitHub Actions workflow automates the creation of releases for the FastWrap ## Trigger -The workflow is automatically triggered when creating a new tag starting with `v` (e.g., `v0.3.3`). +The workflow is automatically triggered when creating a new tag starting with `v` (e.g., `vx.y.z`). ## Generated Artifacts @@ -46,23 +46,23 @@ The workflow generates 4 types of artifacts for different installation methods: Edit [Properties/AssemblyInfo.cs](../Properties/AssemblyInfo.cs): ```csharp -[assembly: AssemblyVersion("0.3.3.0")] -[assembly: AssemblyFileVersion("0.3.3.0")] +[assembly: AssemblyVersion("x.y.z.0")] +[assembly: AssemblyFileVersion("x.y.z.0")] ``` Optional: Update [FastWrappers_TSQL.sqlproj](../FastWrappers_TSQL.sqlproj): ```xml -0.3.3.0 +x.y.z.0 ``` ### 2. Commit and Tag ```bash git add Properties/AssemblyInfo.cs -git commit -m "Bump version to 0.3.3" -git tag v0.3.3 +git commit -m "Bump version to x.y.z" +git tag vx.y.z git push origin main -git push origin v0.3.3 +git push origin vx.y.z ``` ### 3. Verify the Release From 367de356c2fe7f611e0e3db9c9ded54d63be91bd Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Wed, 18 Mar 2026 09:34:11 +0100 Subject: [PATCH 33/37] =?UTF-8?q?feat:=20script=20SQL=20avec=20assembly=20?= =?UTF-8?q?inject=C3=A9=20+=20extraction=20binaire=20dans=20GitHub=20Actio?= =?UTF-8?q?n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Modification de la GitHub Action pour extraire le binaire de l'assembly depuis la base déployée - Création d'un nouveau template FastWrappers-TSQL.sql avec placeholder __ASSEMBLY_FROM_0X__ - Le binaire est injecté automatiquement pendant le build - Utilise sp_add_trusted_assembly pour plus de sécurité - Crée la base de données, l'assembly, les SP (FastTransfer et FastBCP) et les roles - Script complet prêt à l'emploi avec vérifications --- .github/workflows/release.yml | 36 +++- FastWrappers-TSQL.sql | 339 ++++++++++++++++++++++++++-------- 2 files changed, 290 insertions(+), 85 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1d64193..c37d624 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -139,12 +139,38 @@ jobs: Write-Warning "Failed to create BAK file, continuing..." } - # Generate SQL script from DACPAC (includes the compiled binary) - Write-Host "Generating SQL script from DACPAC..." - & $sqlPackage /Action:Script /SourceFile:$dacpacPath /TargetServerName:$serverInstance /TargetDatabaseName:"${dbName}_Script" /OutputPath:$generatedSqlPath /p:IncludeCompositeObjects=True /p:CommentOutSetVarDeclarations=True + # Generate SQL script with current assembly binary + Write-Host "Generating SQL script with assembly binary..." - if ($LASTEXITCODE -ne 0) { - Write-Warning "Failed to generate SQL script, continuing..." + # Extract assembly binary from deployed database using SqlClient (no size limitations) + $connectionString = "Server=$serverInstance;Database=$dbName;Integrated Security=True;TrustServerCertificate=True;" + $connection = New-Object System.Data.SqlClient.SqlConnection($connectionString) + $connection.Open() + + $command = $connection.CreateCommand() + $command.CommandText = "SELECT content FROM sys.assembly_files WHERE assembly_id = (SELECT assembly_id FROM sys.assemblies WHERE name = 'FastWrappers_TSQL')" + + $reader = $command.ExecuteReader() + $assemblyHex = $null + + if ($reader.Read()) { + $bytes = $reader.GetSqlBytes(0).Value + $hexString = [System.BitConverter]::ToString($bytes) -replace '-','' + $assemblyHex = "0x$hexString" + Write-Host "Assembly binary extracted (length: $($assemblyHex.Length) chars, $($bytes.Length) bytes)" + } + + $reader.Close() + $connection.Close() + + if ($assemblyHex) { + # Read template and inject assembly binary + $sqlTemplate = Get-Content "FastWrappers-TSQL.sql" -Raw + $finalSql = $sqlTemplate -replace '__ASSEMBLY_FROM_0X__', $assemblyHex + $finalSql | Out-File -FilePath $generatedSqlPath -Encoding UTF8 + Write-Host "SQL script generated successfully" + } else { + Write-Warning "Failed to extract assembly binary" } # Copy DACPAC with proper name diff --git a/FastWrappers-TSQL.sql b/FastWrappers-TSQL.sql index ae295b6..9cdcec7 100644 --- a/FastWrappers-TSQL.sql +++ b/FastWrappers-TSQL.sql @@ -1,88 +1,110 @@ -/***************************************************************************************************** - * REFERENCE FILE - DO NOT USE IN PRODUCTION - * =================================================================================================== - * - * This SQL file contains a static compiled binary that may be outdated. - * - * To deploy FastWrappers-TSQL, download the automatically generated SQL file from: - * https://github.com/aetperf/FastWrappers-TSQL/releases/latest - * - * The release SQL file is automatically generated by GitHub Actions and contains - * the up-to-date compiled binary (CREATE ASSEMBLY ... FROM 0x4D5A9000...). - * - * This file is kept only as a structure reference. - * - *****************************************************************************************************/ - -USE [FastWrappers-TSQL] -GO -/****** Object: DatabaseRole [FastTransfer_Executor] Script Date: 2025-10-13 23:19:40 ******/ -CREATE ROLE [FastTransfer_Executor] -GO -/****** Object: SqlAssembly [FastWrappers_TSQL] Script Date: 2025-10-13 23:19:40 ******/ -CREATE ASSEMBLY [FastWrappers_TSQL] -FROM 0x4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C0103007968ED680000000000000000E00022200B013000004400000008000000000000CE62000000200000008000000000001000200000000200000400000000000000060000000000000000C0000000020000A20801000300608500001000001000000000100000100000000000001000000000000000000000007C6200004F00000000800000440400000000000000000000000000000000000000A000000C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E7465787400000008430000002000000044000000020000000000000000000000000000200000602E7273726300000044040000008000000006000000460000000000000000000000000000400000402E72656C6F6300000C00000000A0000000020000004C00000000000000000000000000004000004200000000000000000000000000000000B0620000000000004800000002000500EC330000102E000009000000000000000000000000000000FC610000800000000000000000000000000000000000000000000000000000000000000000000000860F00280F00000A2C067E1000000A2A0F00281100000A2805000006731200000A2A000013302200B600000001000011140A0F02280F00000A2D0C04281300000A28060000060A140B0F08280F00000A2D0D0E08281300000A28060000060B140C0F0F280F00000A2D0D0E0F281300000A28060000060C140D0F13280F00000A2D0D0E13281300000A28060000060D020306281400000A050E040E050E060E0707281400000A0E090E0A0E0B0E0C0E0D0E0E08281400000A0E100E110E1209281400000A0E140E150E160E170E180E190E1A0E1B0E1C0E1D0E1E0E1F0E200E2128030000062A00001B3006006E100000020000110F00280F00000A2D0E0F00281100000A6F1500000A2B01140A0F01280F00000A2D130F01281100000A6F1500000A6F1600000A2B01140B0F02280F00000A2D0E0F02281100000A6F1500000A2B01140C0F03280F00000A2D0E0F03281100000A6F1500000A2B01140D0F04280F00000A2D0E0F04281100000A6F1500000A2B011413040F05280F00000A2D0E0F05281100000A6F1500000A2B011413050F06281700000A2D090F06281800000A2B011613060F07280F00000A2D0E0F07281100000A6F1500000A2B011413070F08280F00000A2D0E0F08281100000A6F1500000A2B011413080F09280F00000A2D0E0F09281100000A6F1500000A2B011413090F0A280F00000A2D0E0F0A281100000A6F1500000A2B0114130A0F0B280F00000A2D0E0F0B281100000A6F1500000A2B0114130B0F0C280F00000A2D0E0F0C281100000A6F1500000A2B0114130C0F0D280F00000A2D0E0F0D281100000A6F1500000A2B0114130D0F0E280F00000A2D130F0E281100000A6F1500000A6F1600000A2B0114130E0F0F280F00000A2D0E0F0F281100000A6F1500000A2B0114130F0F10280F00000A2D0E0F10281100000A6F1500000A2B011413100F11281700000A2D090F11281800000A2B011613110F12280F00000A2D0E0F12281100000A6F1500000A2B011413120F13280F00000A2D0E0F13281100000A6F1500000A2B011413130F14280F00000A2D0E0F14281100000A6F1500000A2B011413140F15280F00000A2D0E0F15281100000A6F1500000A2B011413150F16280F00000A2D0E0F16281100000A6F1500000A2B011413160F17280F00000A2D0E0F17281100000A6F1500000A2B011413170F18281900000A2D0E0F18281A00000A731B00000A2B0A122DFE150100001B112D13180F19280F00000A2D0E0F19281100000A6F1500000A2B011413190F1A280F00000A2D0E0F1A281100000A6F1500000A2B0114131A0F1B281900000A2D0E0F1B281A00000A731B00000A2B0A122DFE150100001B112D131B0F1C280F00000A2D0E0F1C281100000A6F1500000A2B0114131C0F1D280F00000A2D0E0F1D281100000A6F1500000A2B0114131D0F1E280F00000A2D0E0F1E281100000A6F1500000A2B0114131E0F1F281700000A2D090F1F281800000A2D03162B0117131F0F20280F00000A2D0E0F20281100000A6F1500000A2B01141320720100007013210F21280F00000A2D5E0F21281100000A6F1500000A6F1600000A132E1A8D2000000125167219000070A225177225000070A225187201000070A225197235000070A2112E280100002B162F177241000070112E7269000070281D00000A731E00000A7A112E132106281F00000A2C0B7226010070731E00000A7A1F0D8D20000001251672D1010070A2251772E7010070A2251872F5010070A22519720F020070A2251A7219020070A2251B7225020070A2251C7231020070A2251D723D020070A2251E7247020070A2251F097253020070A2251F0A7261020070A2251F0B726F020070A2251F0C727B020070A21322112207280100002B162F3C1B8D200000012516728D020070A2251707A2251872CD020070A2251972FB0200701122282000000AA2251A7201030070A2282100000A731E00000A7A1F0A8D2000000125167205030070A2251772E7010070A225187223030070A225197235030070A2251A7243030070A2251B7257030070A2251C7265030070A2251D7275030070A2251E7261020070A2251F09727B020070A213231123110E280100002B162F3D1B8D2000000125167289030070A22517110EA2251872CD020070A2251972FB0200701123282000000AA2251A7201030070A2282100000A731E00000A7A08282200000A16FE01132411242C3709282200000A2C241109282200000A2C1B1107282200000A2C121108282200000A2C091104282200000A2D5C72C9030070731E00000A7A09282200000A2C141104282200000A2C0B7274040070731E00000A7A1109282200000A2C0B7211050070731E00000A7A11062D1D1107282200000A2D091108282200000A2C0B7291050070731E00000A7A161325110A282200000A2D06112517581325110B282200000A2D06112517581325110C282200000A2D0F110D282200000A2D0611251758132511252D0B7218060070731E00000A7A16110A282200000A2D06112517581325110B282200000A2D0611251758132517310B72C3060070731E00000A7A110F282200000A16FE01132611262C2F1110282200000A2C1B1114282200000A2C121112282200000A2C091113282200000A2D547221070070731E00000A7A1110282200000A2C0B72C4070070731E00000A7A1114282200000A2C0B7238080070731E00000A7A11112D1D1112282200000A2D091113282200000A2C0B72B0080070731E00000A7A1115282200000A2D091116282200000A2C0B7237090070731E00000A7A1119282200000A16FE011327112739E10000001E8D200000012516728D090070A225177297090070A2251872A5090070A2251972BB090070A2251A72CB090070A2251B72D7090070A2251C72E1090070A2251D72ED090070A21119280100002B162F1772050A0070111972290A0070281D00000A731E00000A7A1119728D0900706F2300000A2D6C111972970900706F2300000A2D2A111972A50900706F2300000A2D1C111972BB0900706F2300000A2D0E111972CB0900706F2300000A2C20111A282200000A2C1772340B0070111972560B0070281D00000A731E00000A7A121B282400000A2D0B72AC0B0070731E00000A7A1117282200000A16FE012C37188D20000001251672330C0070A2251772410C0070A21117280100002B162F1772530C00701117727B0C0070281D00000A731E00000A7A111C282200000A16FE01132811282C37188D200000012516720C0D0070A22517721E0D0070A2111C280100002B162F1772280D0070111C72520D0070281D00000A731E00000A7A061329112972DF0D00701B6F2500000A2D50112972010E00701B6F2500000A2D411129721B0E00706F2600000A2D251129721F0E00706F2600000A2D1711297E2700000A132F122F282800000A282900000A1329112972DF0D0070282900000A13297E2A00000A132A112A72230E0070072804000006281D00000A132A11242C19112A72550E0070082804000006281D00000A132A38B000000009282200000A2D34112A72850E0070092804000006281D00000A132A1105282200000A2D2C112A72A70E007011052804000006281D00000A132A2B15112A72CD0E007011042804000006281D00000A132A11062C10112A72E90E0070282900000A132A2B361B8D200000012516112AA22517720B0F0070A2251811072804000006A2251972290F0070A2251A11082804000006A2282100000A132A112A724F0F007011092804000006281D00000A132A110A282200000A2D17112A72750F0070110A2804000006281D00000A132A2B1E110B282200000A2D15112A72910F0070110B2804000006281D00000A132A110D282200000A2D33110C282200000A2D2A112A72A50F0070110C2804000006281D00000A132A112A72C70F0070110D2804000006281D00000A132A112A72E70F0070110E2804000006281D00000A132A11262C17112A7219100070110F2804000006281D00000A132A2B74112A724910007011102804000006281D00000A132A11112C10112A726B100070282900000A132A2B361B8D200000012516112AA22517728D100070A2251811122804000006A2251972AB100070A2251A11132804000006A2282100000A132A112A72D110007011142804000006281D00000A132A112A72F710007011152804000006281D00000A132A112A721911007011162804000006281D00000A132A1117282200000A2D15112A723911007011172804000006281D00000A132A1218282400000A2C1F112A72531100701218282B00000A8C26000001282C00000A282900000A132A11273994000000112A727511007011192804000006281D00000A132A1119728D0900701B6F2D00000A2D701119728B1100701B6F2D00000A2D2D111972991100701B6F2D00000A2D1E111972AF1100701B6F2D00000A2D0F111972BF1100701B6F2D00000A2C15112A72CB110070111A2804000006281D00000A132A112A72FB110070121B282B00000A8C26000001282C00000A282900000A132A11282C15112A7217120070111C2804000006281D00000A132A111D282200000A2D15112A7233120070111D2804000006281D00000A132A111E282200000A2D15112A7247120070111E2804000006281D00000A132A1120282200000A2D15112A726912007011202804000006281D00000A132A1121282200000A2D15112A728112007011212804000006281D00000A132A112A6F1500000A132A112A132B112B729B12007072D1120070282E00000A132B112B7209130070723F130070282E00000A132B112B727713007072B7130070282E00000A132B112B72F91300707239140070282E00000A132B111F2C37282F00000A1B8D200000012516727B140070A225171129A2251872A7140070A22519112BA2251A283000000AA2282100000A6F3100000A733200000A2511296F3300000A25112A6F3400000A25166F3500000A25176F3600000A25176F3700000A25176F3800000A132C112C283900000A133011306F3A00000A6F3B00000A133111306F3C00000A6F3B00000A133211306F3D00000A11306F3E00000A1333111F2C4F1131282200000A2D4620A00F0000133E16133F2B2F1131113F113E11316F3F00000A113F59284000000A6F4100000A1340282F00000A11406F3100000A113F113E58133F113F11316F3F00000A32C611316F3F00000A20B80B00003116113111316F3F00000A20B80B0000596F4200000A1331113172AB140070284300000A6F4400000A176F4500000A6F4600000A1334113172D9140070284300000A6F4400000A176F4500000A6F4600000A13351131720D150070284300000A6F4400000A176F4500000A6F4600000A13361131723D150070284300000A6F4400000A176F4500000A6F4600000A13371F098D310000012516726F1500701F0C20800000006A734700000AA22517728D1500701F0C20800000006A734700000AA2251872A71500701F0C20800000006A734700000AA2251972BF15007016734800000AA2251A72D31500701E734800000AA2251B72ED15007016734800000AA2251C720316007016734800000AA2251D721B1600701E734800000AA2251E72291600701F0C156A734700000AA2734900000A13387E2A00000A133911332C23723716007011338C26000001282C00000A13391139283000000A1131281D00000A13391138161114252D06267E2A00000A6F4A00000A1138171115252D06267E2A00000A6F4A00000A1138181116252D06267E2A00000A6F4A00000A1138191134123A284B00000A2D04166A2B02113A6F4C00000A11381A1135123B284D00000A2D03162B02113B6F4E00000A11381B1136123C284B00000A2D04166A2B02113C6F4C00000A11381C1137123D284B00000A2D04166A2B02113D6F4C00000A11381D11336F4E00000A11381E11396F4A00000A282F00000A11386F4F00000A282F00000A11386F5000000A282F00000A6F5100000A1132282200000A2D16282F00000A72C81600701132282900000A6F3100000A11332C1772F616007011338C26000001282C00000A735200000A7ADE0C11302C0711306F5300000ADCDE1B1341725017007011416F5400000A282900000A1141735500000A7A2A00004134000002000000490D0000FB020000441000000C0000000000000000000000400D000012030000521000001B0000001700000146728C17007002728C170070281D00000A2A00001B3003009300000003000011022D02142A285600000A0A067E010000046F5700000A067E020000046F5800000A06176F5900000A06186F5A00000A735B00000A0B066F5C00000A0C070817735D00000A0D09735E00000A13041104026F5F00000ADE2011042C0711046F5300000ADC092C06096F5300000ADC082C06086F5300000ADC076F6000000A286100000A1305DE0A062C06066F5300000ADC11052A000134000002004D000A57000C00000000020045001E63000A0000000002003C00316D000A0000000002000B007B86000A000000001B300300A00000000400001102282200000A2C02142A02286200000A0A285600000A0B077E010000046F5700000A077E020000046F5800000A07176F5900000A07186F5A00000A06736300000A0C076F6400000A0D080916735D00000A13041104736500000A130511056F3B00000A1306DE3611052C0711056F5300000ADC11042C0711046F5300000ADC092C06096F5300000ADC082C06086F5300000ADC072C06076F5300000ADC11062A0140000002005C000B67000C00000000020053002073000C0000000002004900367F000A00000000020042004789000A00000000020017007C93000A00000000BE1F208D3C00000125D004000004286600000A80010000041F108D3C00000125D003000004286600000A80020000042A42534A4201000100000000000C00000076342E302E33303331390000000005006C00000098070000237E000004080000C40A000023537472696E677300000000C81200009017000023555300582A0000100000002347554944000000682A0000A803000023426C6F62000000000000000200000157950228090A000000FA013300160000010000003E00000006000000040000000700000048000000660000000F0000000200000004000000010000000200000001000000030000000200000001000000000098060100000000000600F304D60806006005D60806002904BF080F00F608000006003D0434070600D60434070600A204340706004705340706001305340706002C05340706006A04340706008504340706007E09DC060A00C10421080A00EC0505090A00540421080A000C0705090A004B00050906002300DC060E007907BF080E005A09BF080A000002210806005E07DC0606000E04D6080600D208910A0600C60649010600FB06910A0600B906910A0600090849010600A707490106001903DC0606003806DC0606007C0ADC0606005607DC0606006807DC0606005A0649010600A207DC0606005700DC060E00640A21090A00370A21080A00070321080600BA09DC060600B407490106005506DC060E004F0621090E00460721090E008A0721090E00C20321090A00960121080A000F038A010600E200DC060600B902DC060600E306910A06008302910A06006602910A0600CC06490106007202910A0600160849010600ED09DC0606009205DC0606004B09D6080600C502DC060000000005010000000001000100810110005301E70735000100010081011000CE07E707350001000500000100000E01000035000300080015010000E80000007D0005000800150100002E0000007D000500080031008A0A820231006A01820233015D00860233019E008A02502000000000960031068E02010074200000000096004D03950202003821000000009100730695022400E8310000000093000100DD024600FC31000000009600D109DD024700D032000000009600C609DD024800BC330000000091189808E2024900000001002D0A000001005608000002002303000003008E03000004003C08000005003F0100000600BF0700000700B10100000800F30700000900640300000A00CA0300000B00F50900000C00AE0A00000D00700100000E00A10200000F00380300001000A80300001100490800001200C10100001300FE0700001400790300001500D903000016007D0100001700AD02000018005D0200001900AE0500001A00F90100001B00200700001C008E0200001D00EF0100001E00AB0100001F00D80200002000490600002100E803000022008F0600000100560800000200230300000300FF05000004003C08000005003F0100000600BF0700000700B10100000800F307000009000E0200000A00CA0300000B00F50900000C00AE0A00000D00700100000E00A10200000F00380300001000130600001100490800001200C10100001300FE07000014001D0200001500D903000016007D0100001700AD02000018005D0200001900AE0500001A00F90100001B00200700001C008E0200001D00EF0100001E00AB0100001F00D80200002000490600002100E803000022008F06000001008B06000001002D0A00000100DA07090092080100110092080600190092080A00290092081000310092081000390092081000410092081000490092081000510092081000590092081000610092081000710092080600810092080600C100920806007900AE0615007900B4061900790097051D00790092081000790091092800790085092E000101F6061D000101A9091D008900AE0615008900970515009100AE061500910097058B000C00920895000901B8059B0001017009A90011019208100001013402B00001011B07B50001017009BC000101B40AB00001011A09C2000C00A105150001016A06C70001016A06C20021019007CF002901F6051D0001017009D2000101BC0AD8000C009705DB0001017709E00001011A09C70039012C02A9004101FE02E6005101F202EC004901EA011000A10092080600A100E5021000A10062091000A1007E05F000A100120AF000A1007808F000A100510AF000A900E709F500A900FF09FC005901D1011D00A9006608FC00A9009D090600A90047028B0001015F068B0061011707010101013F06070101013F060D0139014F061201690140091A017101D3062001810197051D00890192082701890192083001B10092083801B100270640019901F8034601B100DF004D013101F8035301B10054005A014901DC0960014901420A60014901DB010600B90092081000A101F0030600B90095021D00B90092086601C90001047B01A901820A8001A90163018001A90154028601A901C0058D01D10092080600A901AF089401E10092089901E9009208A501D10108041000D1007A0AAC01D901DD05B101D901CC05C701D10092088001A9019F089401F1009208A501E9016A0ACD0120006300A0032E000B00E6022E001300EF022E001B000E032E00230017032E002B0028032E00330056032E003B005C032E0043007C032E004B005C032E00530056032E005B00930340006B00A00380007300A00383007300A00301001000000005000100200000000600210034006D01B7018F00D86200000300E8620000040004800000000002000200000001000000E0012D010000040000000000000000000000D701A20100000000040000000000000000000000D7018A0100000000040000000000000000000000D701DC060000000005000400060004003900A5000000003C52756E466173745472616E73666572496E7465726E616C3E675F5F517C325F30004E756C6C61626C656031005F5F5374617469634172726179496E69745479706553697A653D33320053716C496E74333200536574496E7433320030354145344342453746383731373632353633433643363833333034313330444538313839374632343835313146343731423234413943433536303831463033004232363132444333343241453031374341344339413441443431313732463238443333304532433035343036343935443042393843323933343633333344333400536574496E743634005F5F5374617469634172726179496E69745479706553697A653D3136003C4D6F64756C653E003C50726976617465496D706C656D656E746174696F6E44657461696C733E004661737457726170706572735F5453514C00736F7572636544534E0053797374656D2E494F00466173745472616E73666572434C52007365745F495600416573495600736F75726365536368656D6100746172676574536368656D610053797374656D2E446174610053716C4D65746144617461006D73636F726C69620072756E4964006973536F7572636554727573746564006973546172676574547275737465640052656164546F456E640053656E64526573756C7473456E640053656E64006D61704D6574686F64006D6574686F640053716C446174615265636F726400736F7572636550617373776F72640074617267657450617373776F7264005265706C6163650049734E756C6C4F7257686974655370616365006765745F45786974436F6465007365745F4D6F6465006C6F61644D6F64650050616464696E674D6F64650043727970746F53747265616D4D6F6465004369706865724D6F646500646567726565006765745F4D65737361676500736F757263655461626C65007461726765745461626C650049446973706F7361626C650052756E74696D654669656C6448616E646C650073657474696E677346696C65007365745F46696C654E616D65006765745F4E65774C696E65006765745F506970650053716C506970650053716C4462547970650056616C75655479706500736F75726365436F6E6E656374696F6E5479706500746172676574436F6E6E656374696F6E547970650052756E466173745472616E736665725F53656375726500736F7572636550617373776F72645365637572650074617267657450617373776F726453656375726500736F75726365436F6E6E656374537472696E6753656375726500746172676574436F6E6E656374537472696E67536563757265004361707475726500736F757263654461746162617365007461726765744461746162617365006C6963656E736500446973706F73650054727950617273650043726561746500577269746500436F6D70696C657247656E6572617465644174747269627574650044656275676761626C6541747472696275746500417373656D626C795469746C654174747269627574650053716C50726F63656475726541747472696275746500417373656D626C7954726164656D61726B41747472696275746500417373656D626C7946696C6556657273696F6E41747472696275746500417373656D626C79436F6E66696775726174696F6E4174747269627574650053716C46756E6374696F6E41747472696275746500417373656D626C794465736372697074696F6E41747472696275746500436F6D70696C6174696F6E52656C61786174696F6E7341747472696275746500417373656D626C7950726F6475637441747472696275746500417373656D626C79436F7079726967687441747472696275746500417373656D626C79436F6D70616E794174747269627574650052756E74696D65436F6D7061746962696C697479417474726962757465007365745F5573655368656C6C457865637574650042797465006765745F56616C7565006765745F48617356616C756500626174636853697A6500496E6465784F66007365745F50616464696E670046726F6D426173653634537472696E6700546F426173653634537472696E670053716C537472696E6700546F537472696E6700736F75726365436F6E6E656374537472696E6700746172676574436F6E6E656374537472696E6700536574537472696E6700456E6372797074537472696E6700537562737472696E67006465627567004D61746368004D6174680050617468006765745F4C656E67746800456E6473576974680052756E466173745472616E73666572496E7465726E616C0076616C006C6F676C6576656C004661737457726170706572735F5453514C2E646C6C006765745F49734E756C6C0043727970746F53747265616D004D656D6F727953747265616D006765745F4974656D0053797374656D0053796D6D6574726963416C676F726974686D005472696D004943727970746F5472616E73666F726D0053716C426F6F6C65616E004D696E004A6F696E00646973747269627574654B6579436F6C756D6E0053797374656D2E5265666C656374696F6E0047726F7570436F6C6C656374696F6E00417267756D656E74457863657074696F6E00537472696E67436F6D70617269736F6E0050726F636573735374617274496E666F0047726F7570004469726563746F7279536570617261746F72436861720053747265616D526561646572005465787452656164657200736F7572636550726F7669646572004B657950726F76696465720062617365363443697068657200466173745772617070657200736F757263655573657200746172676574557365720053747265616D5772697465720054657874577269746572004D6963726F736F66742E53716C5365727665722E53657276657200736F757263655365727665720074617267657453657276657200666173745472616E73666572446972006765745F5374616E646172644572726F72007365745F52656469726563745374616E646172644572726F72002E63746F72002E6363746F7200437265617465446563727970746F7200437265617465456E63727970746F720053797374656D2E446961676E6F7374696373004165730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300446562756767696E674D6F6465730053797374656D2E446174612E53716C547970657300457175616C730053797374656D2E546578742E526567756C617245787072657373696F6E73006765745F47726F7570730052756E74696D6548656C706572730050726F63657373007365745F417267756D656E747300436F6E63617400466F726D6174004F626A656374006F705F496D706C69636974006F705F4578706C696369740057616974466F724578697400546F4C6F776572496E76617269616E7400456E7669726F6E6D656E74004165734465637279707400416573456E63727970740053656E64526573756C7473537461727400436F6E766572740066696C65496E707574006765745F5374616E646172644F7574707574007365745F52656469726563745374616E646172644F757470757400706C61696E546578740053716C436F6E746578740053656E64526573756C7473526F77007365745F4372656174654E6F57696E646F7700526567657800496E697469616C697A65417272617900546F4172726179007365745F4B6579004165734B65790053797374656D2E53656375726974792E43727970746F6772617068790071756572790049734E756C6C4F72456D707479000000001769006E0066006F0072006D006100740069006F006E00000B6500720072006F007200000F7700610072006E0069006E006700000B64006500620075006700002749006E00760061006C006900640020006C006F0067006C006500760065006C003A00200027000180BB27002E002000550073006500200027006500720072006F00720027002C00200027007700610072006E0069006E00670027002C002000270069006E0066006F0072006D006100740069006F006E0027002C0020006F007200200027006400650062007500670027002E0020005700410052004E0049004E0047002000740068006500200070006100720061006D006500740065007200200069007300200043006100730065002000530065006E007300690074006900760065000180A966006100730074005400720061006E00730066006500720044006900720020006D007500730074002000620065002000700072006F0076006900640065006400200028006400690072006500630074006F0072007900200063006F006E007400610069006E0069006E0067002000740068006500200046006100730074005400720061006E0073006600650072002000650078006500630075007400610062006C00650029002E00001563006C00690063006B0068006F00750073006500000D6400750063006B006400620000196400750063006B0064006200730074007200650061006D000009680061006E006100000B6D007300730071006C00000B6D007900730071006C00000B6E007A00730071006C0000096F00640062006300000B6F006C00650064006200000D6F00720061006F0064007000000D7000670063006F0070007900000B70006700730071006C00001174006500720061006400610074006100003F49006E00760061006C0069006400200053006F00750072006300650043006F006E006E0065006300740069006F006E0054007900700065003A0020002700012D27002E00200050006F0073007300690062006C0065002000760061006C00750065002000610072006500200001052C00200000032E00001D63006C00690063006B0068006F00750073006500620075006C006B000011680061006E006100620075006C006B00000D6D007300620075006C006B0000136D007900730071006C00620075006C006B00000D6E007A00620075006C006B00000F6F0072006100620075006C006B0000136F0072006100640069007200650063007400003F49006E00760061006C0069006400200054006100720067006500740043006F006E006E0065006300740069006F006E0054007900700065003A00200027000180A95700680065006E00200073006F00750072006300650043006F006E006E0065006300740053007400720069006E0067002000690073002000700072006F00760069006400650064002C00200064006F0020006E006F007400200073007500700070006C00790020007300650072007600650072002F00440053004E002F00630072006500640065006E007400690061006C0073002F00640061007400610062006100730065002E0000809B4D007500730074002000700072006F0076006900640065002000650069007400680065007200200073006F00750072006300650053006500720076006500720020006F007200200073006F007500720063006500440053004E00200069006600200073006F00750072006300650043006F006E006E0065006300740053007400720069006E00670020006900730020004E0055004C004C002E00007F4D007500730074002000700072006F007600690064006500200073006F0075007200630065004400610074006100620061007300650020007700680065006E0020006E006F00740020007500730069006E006700200073006F00750072006300650043006F006E006E0065006300740053007400720069006E0067002E000080854D007500730074002000700072006F007600690064006500200073006F0075007200630065005500730065007200200061006E006400200073006F007500720063006500500061007300730077006F007200640020007700680065006E00200073006F007500720063006500540072007500730074006500640020003D00200030002E000080A959006F00750020006D00750073007400200073007500700070006C00790020006100740020006C00650061007300740020006F006E00650020006F0066002000660069006C00650049006E007000750074002C002000710075006500720079002C0020006F0072002000280073006F00750072006300650053006300680065006D006100200041004E004400200073006F0075007200630065005400610062006C00650029002E00005D59006F00750020006D00750073007400200073007500700070006C00790020006F006E006C00790020006F006E00650020006F0066002000660069006C00650049006E0070007500740020006F0072002000710075006500720079000080A15700680065006E00200074006100720067006500740043006F006E006E0065006300740053007400720069006E0067002000690073002000700072006F00760069006400650064002C00200064006F0020006E006F007400200073007500700070006C00790020007300650072007600650072002F00630072006500640065006E007400690061006C0073002F00640061007400610062006100730065002E0000734D007500730074002000700072006F0076006900640065002000740061007200670065007400530065007200760065007200200069006600200074006100720067006500740043006F006E006E0065006300740053007400720069006E00670020006900730020004E0055004C004C002E0000774D007500730074002000700072006F007600690064006500200074006100720067006500740044006100740061006200610073006500200069006600200074006100720067006500740043006F006E006E0065006300740053007400720069006E00670020006900730020004E0055004C004C002E000080854D007500730074002000700072006F00760069006400650020007400610072006700650074005500730065007200200061006E0064002000740061007200670065007400500061007300730077006F007200640020007700680065006E002000740061007200670065007400540072007500730074006500640020003D00200030002E0000554D007500730074002000700072006F007600690064006500200074006100720067006500740053006300680065006D006100200061006E00640020007400610072006700650074005400610062006C0065002E0000094E006F006E006500000D520061006E0064006F006D0000154400610074006100440072006900760065006E00000F520061006E006700650049006400000B4E00740069006C00650000094300740069006400000B52006F0077006900640000174E005A00440061007400610053006C00690063006500002349006E00760061006C006900640020006D006500740068006F0064003A002000270001810927002E002000750073006500200027004E006F006E00650027002C0020002700520061006E0064006F006D0027002C00200027004400610074006100440072006900760065006E0027002C0020002700520061006E00670065004900640027002C00200027004E00740069006C00650027002C00200027004E005A00440061007400610053006C0069006300650027002C00200027004300740069006400270020006F0072002000270052006F0077006900640027002E0020005700410052004E0049004E0047002000740068006500200070006100720061006D006500740065007200200069007300200043006100730065002000530065006E0073006900740069007600650001215700680065006E0020006D006500740068006F00640020006900730020002700015527002C00200079006F00750020006D007500730074002000700072006F00760069006400650020002D002D0064006900730074007200690062007500740065004B006500790043006F006C0075006D006E002E000180855700680065006E002000730070006500630069006600790069006E0067002000610020006D006500740068006F00640020006F00740068006500720020007400680061006E0020004E006F006E0065002C00200079006F00750020006D007500730074002000700072006F00760069006400650020006400650067007200650065002E00000D41007000700065006E00640000115400720075006E006300610074006500002749006E00760061006C006900640020006C006F00610064006D006F00640065003A002000270001808F27002E0020005500730065002000270041007000700065006E006400270020006F007200200027005400720075006E00630061007400650027002E00200020005700410052004E0049004E0047002000740068006500200070006100720061006D006500740065007200200069007300200043006100730065002000530065006E00730069007400690076006500011150006F0073006900740069006F006E0000094E0061006D006500002949006E00760061006C006900640020006D00610070004D006500740068006F0064003A002000270001808B27002E0020007500730065002000270050006F0073006900740069006F006E00270020006F007200200027004E0061006D00650027002E00200020005700410052004E0049004E0047002000740068006500200070006100720061006D006500740065007200200069007300200043006100730065002000530065006E00730069007400690076006500012146006100730074005400720061006E0073006600650072002E00650078006500001966006100730074007400720061006E00730066006500720000035C0000032F00003120002D002D0073006F00750072006300650063006F006E006E0065006300740069006F006E0074007900700065002000012F20002D002D0073006F00750072006300650063006F006E006E0065006300740073007400720069006E0067002000012120002D002D0073006F0075007200630065007300650072007600650072002000012520002D002D0073006F007500720063006500700072006F00760069006400650072002000011B20002D002D0073006F007500720063006500640073006E002000012120002D002D0073006F0075007200630065007400720075007300740065006400011D20002D002D0073006F00750072006300650075007300650072002000012520002D002D0073006F007500720063006500700061007300730077006F00720064002000012520002D002D0073006F007500720063006500640061007400610062006100730065002000011B20002D002D00660069006C00650069006E007000750074002000011320002D002D00710075006500720079002000012120002D002D0073006F00750072006300650073006300680065006D0061002000011F20002D002D0073006F0075007200630065007400610062006C0065002000013120002D002D0074006100720067006500740063006F006E006E0065006300740069006F006E0074007900700065002000012F20002D002D0074006100720067006500740063006F006E006E0065006300740073007400720069006E0067002000012120002D002D007400610072006700650074007300650072007600650072002000012120002D002D007400610072006700650074007400720075007300740065006400011D20002D002D0074006100720067006500740075007300650072002000012520002D002D00740061007200670065007400700061007300730077006F00720064002000012520002D002D00740061007200670065007400640061007400610062006100730065002000012120002D002D0074006100720067006500740073006300680065006D0061002000011F20002D002D007400610072006700650074007400610062006C0065002000011920002D002D006C006F00610064006D006F00640065002000012120002D002D0062006100740063006800730069007A00650020007B0030007D00011520002D002D006D006500740068006F0064002000010D720061006E0064006F006D0000156400610074006100640072006900760065006E00000F720061006E006700650069006400000B6E00740069006C006500002F20002D002D0064006900730074007200690062007500740065004B006500790043006F006C0075006D006E002000011B20002D002D0064006500670072006500650020007B0030007D00011B20002D002D006D00610070006D006500740068006F0064002000011320002D002D00720075006E00690064002000012120002D002D00730065007400740069006E0067007300660069006C0065002000011720002D002D006C006900630065006E00730065002000011920002D002D006C006F0067006C006500760065006C00200001352D002D0073006F007500720063006500700061007300730077006F00720064005C0073002B0022005B005E0022005D002A00220001372D002D0073006F007500720063006500700061007300730077006F0072006400200022003C00680069006400640065006E003E00220001352D002D00740061007200670065007400700061007300730077006F00720064005C0073002B0022005B005E0022005D002A00220001372D002D00740061007200670065007400700061007300730077006F0072006400200022003C00680069006400640065006E003E002200013F2D002D0073006F00750072006300650063006F006E006E0065006300740073007400720069006E0067005C0073002B0022005B005E0022005D002A00220001412D002D0073006F00750072006300650063006F006E006E0065006300740073007400720069006E006700200022003C00680069006400640065006E003E002200013F2D002D0074006100720067006500740063006F006E006E0065006300740073007400720069006E0067005C0073002B0022005B005E0022005D002A00220001412D002D0074006100720067006500740063006F006E006E0065006300740073007400720069006E006700200022003C00680069006400640065006E003E002200012B46006100730074005400720061006E007300660065007200200043006F006D006D0061006E006400200000032000002D54006F00740061006C00200072006F00770073005C0073002A003A005C0073002A0028005C0064002B002900003354006F00740061006C00200063006F006C0075006D006E0073005C0073002A003A005C0073002A0028005C0064002B002900002F54006F00740061006C002000630065006C006C0073005C0073002A003A005C0073002A0028005C0064002B002900003145006C00610070007300650064005C0073002A003D005C0073002A0028005C0064002B0029005C0073002A006D007300001D74006100720067006500740064006100740061006200610073006500001974006100720067006500740053006300680065006D00610000177400610072006700650074005400610062006C006500001354006F00740061006C0052006F0077007300001954006F00740061006C0043006F006C0075006D006E007300001554006F00740061006C00430065006C006C007300001754006F00740061006C00540069006D0065004D007300000D530074006100740075007300000D53007400640045007200720000808F46006100730074005400720061006E0073006600650072002000700072006F00630065007300730020006600610069006C00650064002000770069007400680020006500780069007400200063006F006400650020007B0030007D002E0020005300650065002000730074006400650072007200200066006F0072002000640065007400610069006C0073002E00002D46006100730074005400720061006E00730066006500720020007300740064006500720072003A000D000A00005946006100730074005400720061006E0073006600650072002000700072006F0063006500730073002000720065007400750072006E006500640020006500780069007400200063006F006400650020007B0030007D002E00003B4500720072006F007200200069006E0076006F006B0069006E006700200046006100730074005400720061006E0073006600650072003A002000000322000077144D9FB1D4AA4AA1CC6E071A6D2BE400042001010803200001052001011111042001010E032000020306113D0320000E0607040E0E0E0E0500010E113D050001113D0E5607420E0E0E0E0E0E020E0E0E0E0E0E0E0E0E0E020E0E0E0E0E0E15114D01080E0E15114D01080E0E0E020E0E1D0E1D0E02080202020E0E0E125115114D01080E0312550E0E080E0E0E0E12590E0A080A0A08080E125D032000080515114D010805200101130009100102081D1E001E00030A010E0600030E0E0E0E040001020E0600020E0E1D0E0500010E1D0E042001020E072002020E11808D0206030500020E0E0E02060E04200013000500020E0E1C0500001280A50300000E04200101020600011255125104200012790500020808080520020E08080420010E080700021280B50E0E0520001280B90620011280BD08082003010E1180C90A072002010E1180C9072001011D1280C505200201080E060002020E100A05200201080A060002020E1008052002010808052001011259062002010E125D0D070612651269126D127112750E0400001265052001011D05062001011180D9062001011180DD042000126D0B2003011280E1126D1180E5062001011280E10420001D050500010E1D050F07071D0512651269126D127112790E0500011D050E090002011280851180F908B77A5C561934E08980A0002400000480000094000000060200000024000052534131000400000100010041AB0C528E5478F2CB94BEC28F84956BAD3F2A208D6CDC21EBFA4BED2B4FACBE543F6F667C69D1597951DE3A1DA78303C687C5F71FFD6A67C3FE52C51BD0395F4163CE187D2807132385C94243BEF17286AA36DD4E52B5B16107D637421417CD8E5DAE1DD0ABB5264EC8DE08015C0D37E46AA6F56707DD23991FC1596328A5D003061D050306111403061118060001113D113D47002201113D113D113D113D113D113D1145113D113D113D113D113D113D113D113D113D113D1145113D113D113D113D113D113D1149113D113D1149113D113D113D1145113D113D0400010E0E030000010801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F7773010801000200000000001001000B466173745772617070657200002D010028434C52205772617070657220666F7220466173745472616E7366657220616E64204661737442435000000501000000001F01001A417263686974656374757265202620506572666F726D616E63650000160100114661737457726170706572735F5453514C00000C010007302E322E322E30000004010000000000003F822C7ADBA3A8882411F02799BE754357F837259CEEFC399D7D695F723BAD51BC44EA6AC0CE8A943400131E30818EAB727D379A9A04C6327144CDEA2FB6F9116BDE6AA19E2E5C909D4C1B657EC94D9CA8A8258C956990A6FB49FD80CE01529EDA6402B4C43D3DB9577239D0EAAC17A789F5141C7145D854AC25C6709F55099EA46200000000000000000000BE620000002000000000000000000000000000000000000000000000B0620000000000000000000000005F436F72446C6C4D61696E006D73636F7265652E646C6C0000000000FF2500200010000000001122AA77559910016633450F3A2BCCEE013358A73B992DFA6211D5E78F2C990AF26844FA4892BE65107ACAAC9EDE7F0C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100100000001800008000000000000000000000000000000100010000003000008000000000000000000000000000000100000000004800000058800000E80300000000000000000000E80334000000560053005F00560045005200530049004F004E005F0049004E0046004F0000000000BD04EFFE00000100020000000000020002000000000002003F000000000000000400000002000000000000000000000000000000440000000100560061007200460069006C00650049006E0066006F00000000002400040000005400720061006E0073006C006100740069006F006E00000000000000B00448030000010053007400720069006E006700460069006C00650049006E0066006F0000002403000001003000300030003000300034006200300000006A002900010043006F006D006D0065006E0074007300000043004C00520020005700720061007000700065007200200066006F007200200046006100730074005400720061006E007300660065007200200061006E006400200046006100730074004200430050000000000056001B00010043006F006D00700061006E0079004E0061006D0065000000000041007200630068006900740065006300740075007200650020002600200050006500720066006F0072006D0061006E00630065000000000040000C000100460069006C0065004400650073006300720069007000740069006F006E0000000000460061007300740057007200610070007000650072000000300008000100460069006C006500560065007200730069006F006E000000000030002E0032002E0032002E00300000004C001600010049006E007400650072006E0061006C004E0061006D00650000004600610073007400570072006100700070006500720073005F005400530051004C002E0064006C006C0000005A001B0001004C006500670061006C0043006F007000790072006900670068007400000041007200630068006900740065006300740075007200650020002600200050006500720066006F0072006D0061006E0063006500000000002A00010001004C006500670061006C00540072006100640065006D00610072006B00730000000000000000005400160001004F0072006900670069006E0061006C00460069006C0065006E0061006D00650000004600610073007400570072006100700070006500720073005F005400530051004C002E0064006C006C000000440012000100500072006F0064007500630074004E0061006D006500000000004600610073007400570072006100700070006500720073005F005400530051004C000000340008000100500072006F006400750063007400560065007200730069006F006E00000030002E0032002E0032002E003000000038000800010041007300730065006D0062006C0079002000560065007200730069006F006E00000030002E0032002E0032002E003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000C000000D03200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -WITH PERMISSION_SET = UNSAFE +-- ===================================================================== +-- FastWrappers-TSQL - Complete Installation Script +-- ===================================================================== +-- This script creates the FastWrappers-TSQL database with all +-- required CLR assemblies, stored procedures, functions, and security roles. +-- ===================================================================== +-- Prerequisites: +-- 1. SQL Server 2016 or later +-- 2. CLR integration enabled (see instructions below) +-- 3. FastTransfer and FastBCP binaries available +-- ===================================================================== + +-- ===================================================================== +-- STEP 1: Enable CLR Integration (if not already enabled) +-- ===================================================================== +EXEC sp_configure 'show advanced options', 1; +RECONFIGURE; GO -/****** Object: UserDefinedFunction [dbo].[EncryptString] Script Date: 2025-10-13 23:19:40 ******/ -SET ANSI_NULLS OFF + +EXEC sp_configure 'clr enabled', 1; +RECONFIGURE; +GO + +-- ===================================================================== +-- STEP 2: Create Database +-- ===================================================================== +USE [master] GO -SET QUOTED_IDENTIFIER OFF + +IF EXISTS (SELECT name FROM sys.databases WHERE name = 'FastWrappers-TSQL') +BEGIN + PRINT 'Database FastWrappers-TSQL already exists. Dropping it...'; + ALTER DATABASE [FastWrappers-TSQL] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; + DROP DATABASE [FastWrappers-TSQL]; +END GO -CREATE FUNCTION [dbo].[EncryptString](@plainText [nvarchar](max)) -RETURNS [nvarchar](max) WITH EXECUTE AS CALLER -AS -EXTERNAL NAME [FastWrappers_TSQL].[FastWrapper.FastTransferCLR].[EncryptString] + +CREATE DATABASE [FastWrappers-TSQL] GO -/****** Object: StoredProcedure [dbo].[RunFastTransfer_Secure] Script Date: 2025-10-13 23:19:40 ******/ -SET ANSI_NULLS OFF + +ALTER DATABASE [FastWrappers-TSQL] SET RECOVERY SIMPLE; GO -SET QUOTED_IDENTIFIER OFF + +ALTER DATABASE [FastWrappers-TSQL] SET PAGE_VERIFY CHECKSUM; GO -CREATE PROCEDURE [dbo].[RunFastTransfer_Secure] - @fastTransferDir [nvarchar](max), - @sourceConnectionType [nvarchar](max), - @sourceConnectStringSecure [nvarchar](max), - @sourceServer [nvarchar](max), - @sourceDSN [nvarchar](max), - @sourceProvider [nvarchar](max), - @isSourceTrusted [bit], - @sourceUser [nvarchar](max), - @sourcePasswordSecure [nvarchar](max), - @sourceDatabase [nvarchar](max), - @fileInput [nvarchar](max), - @query [nvarchar](max), - @sourceSchema [nvarchar](max), - @sourceTable [nvarchar](max), - @targetConnectionType [nvarchar](max), - @targetConnectStringSecure [nvarchar](max), - @targetServer [nvarchar](max), - @isTargetTrusted [bit], - @targetUser [nvarchar](max), - @targetPasswordSecure [nvarchar](max), - @targetDatabase [nvarchar](max), - @targetSchema [nvarchar](max), - @targetTable [nvarchar](max), - @loadMode [nvarchar](max), - @batchSize [int], - @method [nvarchar](max), - @distributeKeyColumn [nvarchar](max), - @degree [int], - @mapMethod [nvarchar](max), - @runId [nvarchar](max), - @settingsFile [nvarchar](max), - @debug [bit], - @license [nvarchar](max), - @loglevel [nvarchar](max) + +PRINT 'Database FastWrappers-TSQL created successfully.'; +GO + +-- ===================================================================== +-- STEP 3: Configure Database for CLR with sp_add_trusted_assembly +-- ===================================================================== +-- This method uses sp_add_trusted_assembly and is more secure +-- The assembly hex will be injected during the build process + +USE [FastWrappers-TSQL]; +GO + +-- Add assembly to trusted list BEFORE creating it +DECLARE @assemblyBinary VARBINARY(MAX) = __ASSEMBLY_FROM_0X__; +DECLARE @hash VARBINARY(64) = HASHBYTES('SHA2_512', @assemblyBinary); + +EXEC sys.sp_add_trusted_assembly + @hash = @hash, + @description = N'FastWrappers_TSQL Assembly'; +GO + +-- Now load the assembly (it's already trusted) +CREATE ASSEMBLY [FastWrappers_TSQL] +FROM __ASSEMBLY_FROM_0X__ +WITH PERMISSION_SET = UNSAFE; +GO + +PRINT 'Assembly loaded and added to trusted list.'; +GO + +-- ===================================================================== +-- STEP 4: Create CLR Function - EncryptString +-- ===================================================================== +USE [FastWrappers-TSQL]; +GO + +IF EXISTS (SELECT * FROM sys.objects WHERE name = 'EncryptString' AND type IN ('FN', 'TF', 'IF', 'FS')) +BEGIN + DROP FUNCTION [dbo].[EncryptString]; +END +GO + +CREATE FUNCTION [dbo].[EncryptString](@plainText [nvarchar](4000)) +RETURNS [nvarchar](4000) WITH EXECUTE AS CALLER -AS -EXTERNAL NAME [FastWrappers_TSQL].[FastWrapper.FastTransferCLR].[RunFastTransfer_Secure] +AS EXTERNAL NAME [FastWrappers_TSQL].[FastWrapper.FastTransferCLR].[EncryptString]; GO -/****** Object: StoredProcedure [dbo].[xp_RunFastTransfer_secure] Script Date: 2025-10-13 23:19:40 ******/ -SET ANSI_NULLS OFF + +PRINT 'Function dbo.EncryptString created successfully.'; GO -SET QUOTED_IDENTIFIER OFF + +-- ===================================================================== +-- STEP 5: Create CLR Stored Procedure - xp_RunFastTransfer_secure +-- ===================================================================== + +IF EXISTS (SELECT * FROM sys.objects WHERE name = 'xp_RunFastTransfer_secure' AND type = 'PC') +BEGIN + DROP PROCEDURE [dbo].[xp_RunFastTransfer_secure]; +END GO + CREATE PROCEDURE [dbo].[xp_RunFastTransfer_secure] @fastTransferDir [nvarchar](max), @sourceConnectionType [nvarchar](30), @@ -90,7 +112,7 @@ CREATE PROCEDURE [dbo].[xp_RunFastTransfer_secure] @sourceServer [nvarchar](255), @sourceDSN [nvarchar](255) = N'', @sourceProvider [nvarchar](1000) = N'', - @isSourceTrusted [bit] = False, + @isSourceTrusted [bit] = 0, @sourceUser [nvarchar](1000) = N'', @sourcePasswordSecure [nvarchar](255) = N'', @sourceDatabase [nvarchar](1000), @@ -101,7 +123,7 @@ CREATE PROCEDURE [dbo].[xp_RunFastTransfer_secure] @targetConnectionType [nvarchar](30), @targetConnectStringSecure [nvarchar](4000) = N'', @targetServer [nvarchar](255), - @isTargetTrusted [bit] = False, + @isTargetTrusted [bit] = 0, @targetUser [nvarchar](1000) = N'', @targetPasswordSecure [nvarchar](255) = N'', @targetDatabase [nvarchar](255), @@ -109,16 +131,173 @@ CREATE PROCEDURE [dbo].[xp_RunFastTransfer_secure] @targetTable [nvarchar](255), @loadMode [nvarchar](50), @batchSize [int] = 1048576, + @useWorkTables [bit] = 0, @method [nvarchar](50) = N'None', @distributeKeyColumn [nvarchar](255) = N'', + @dataDrivenQuery [nvarchar](4000) = N'', @degree [int] = 4, @mapmethod [nvarchar](50) = N'Position', @runId [nvarchar](255) = N'', @settingsFile [nvarchar](4000) = N'', - @debug [bit] = False, + @debug [bit] = 0, + @noBanner [bit] = 0, @license [nvarchar](4000) = N'', @loglevel [nvarchar](50) = N'information' WITH EXECUTE AS CALLER -AS -EXTERNAL NAME [FastWrappers_TSQL].[FastWrapper.FastTransferCLR].[RunFastTransfer_Secure] +AS EXTERNAL NAME [FastWrappers_TSQL].[FastWrapper.FastTransferCLR].[RunFastTransfer_Secure]; +GO + +PRINT 'Stored procedure dbo.xp_RunFastTransfer_secure created successfully.'; +GO + +-- ===================================================================== +-- STEP 6: Create CLR Stored Procedure - xp_RunFastBCP_secure +-- ===================================================================== + +IF EXISTS (SELECT * FROM sys.objects WHERE name = 'xp_RunFastBCP_secure' AND type = 'PC') +BEGIN + DROP PROCEDURE [dbo].[xp_RunFastBCP_secure]; +END +GO + +CREATE PROCEDURE [dbo].[xp_RunFastBCP_secure] + @fastBCPDir [nvarchar](max), + @sourceConnectionType [nvarchar](30), + @sourceConnectStringSecure [nvarchar](4000) = N'', + @sourceServer [nvarchar](255), + @sourceDSN [nvarchar](255) = N'', + @sourceProvider [nvarchar](1000) = N'', + @isSourceTrusted [bit] = 0, + @sourceUser [nvarchar](1000) = N'', + @sourcePasswordSecure [nvarchar](255) = N'', + @sourceDatabase [nvarchar](1000), + @applicationintent [nvarchar](20) = N'ReadOnly', + @query [nvarchar](4000) = N'', + @sourceSchema [nvarchar](255) = N'', + @sourceTable [nvarchar](255) = N'', + @targetFormat [nvarchar](50), + @targetPath [nvarchar](4000), + @targetFileName [nvarchar](500) = N'output', + @partitionSize [int] = 1048576, + @method [nvarchar](50) = N'None', + @distributeKeyColumn [nvarchar](255) = N'', + @degree [int] = 4, + @quotechar [nvarchar](2) = N'"', + @escapechar [nvarchar](2) = N'"', + @delimiter [nvarchar](10) = N',', + @decimalSeparator [nvarchar](2) = N'.', + @parquetcompression [nvarchar](20) = N'zstd', + @runId [nvarchar](255) = N'', + @settingsFile [nvarchar](4000) = N'', + @config [nvarchar](4000) = N'', + @debug [bit] = 0, + @nobanner [bit] = 0, + @license [nvarchar](4000) = N'', + @loglevel [nvarchar](50) = N'information' +WITH EXECUTE AS CALLER +AS EXTERNAL NAME [FastWrappers_TSQL].[FastWrapper.FastBCPCLR].[RunFastBCP_Secure]; +GO + +PRINT 'Stored procedure dbo.xp_RunFastBCP_secure created successfully.'; +GO + +-- ===================================================================== +-- STEP 7: Create Security Roles +-- ===================================================================== + +IF NOT EXISTS (SELECT 1 FROM sys.database_principals WHERE name = 'FastTransfer_Executor' AND type = 'R') +BEGIN + CREATE ROLE [FastTransfer_Executor]; + PRINT 'Role [FastTransfer_Executor] created successfully.'; +END +ELSE +BEGIN + PRINT 'Role [FastTransfer_Executor] already exists.'; +END +GO + +IF NOT EXISTS (SELECT 1 FROM sys.database_principals WHERE name = 'FastBCP_Executor' AND type = 'R') +BEGIN + CREATE ROLE [FastBCP_Executor]; + PRINT 'Role [FastBCP_Executor] created successfully.'; +END +ELSE +BEGIN + PRINT 'Role [FastBCP_Executor] already exists.'; +END +GO + +-- Grant EXECUTE permissions +GRANT EXECUTE ON dbo.xp_RunFastTransfer_secure TO [FastTransfer_Executor]; +GRANT EXECUTE ON dbo.xp_RunFastBCP_secure TO [FastBCP_Executor]; +GRANT EXECUTE ON dbo.EncryptString TO [FastTransfer_Executor]; +GRANT EXECUTE ON dbo.EncryptString TO [FastBCP_Executor]; +GO + +PRINT 'Permissions granted to [FastTransfer_Executor] and [FastBCP_Executor] roles.'; +GO + +-- ===================================================================== +-- STEP 8: Verification +-- ===================================================================== + +PRINT ''; +PRINT '====================================================================='; +PRINT 'Installation Summary'; +PRINT '====================================================================='; +PRINT ''; + +-- Check assembly +IF EXISTS (SELECT * FROM sys.assemblies WHERE name = 'FastWrappers_TSQL') + PRINT '[OK] Assembly [FastWrappers_TSQL] is loaded'; +ELSE + PRINT '[ERROR] Assembly [FastWrappers_TSQL] is NOT loaded!'; + +-- Check function +IF EXISTS (SELECT * FROM sys.objects WHERE name = 'EncryptString' AND type = 'FS') + PRINT '[OK] Function [dbo].[EncryptString] is created'; +ELSE + PRINT '[ERROR] Function [dbo].[EncryptString] is NOT created!'; + +-- Check FastTransfer stored procedure +IF EXISTS (SELECT * FROM sys.objects WHERE name = 'xp_RunFastTransfer_secure' AND type = 'PC') + PRINT '[OK] Stored procedure [dbo].[xp_RunFastTransfer_secure] is created'; +ELSE + PRINT '[ERROR] Stored procedure [dbo].[xp_RunFastTransfer_secure] is NOT created!'; + +-- Check FastBCP stored procedure +IF EXISTS (SELECT * FROM sys.objects WHERE name = 'xp_RunFastBCP_secure' AND type = 'PC') + PRINT '[OK] Stored procedure [dbo].[xp_RunFastBCP_secure] is created'; +ELSE + PRINT '[ERROR] Stored procedure [dbo].[xp_RunFastBCP_secure] is NOT created!'; + +-- Check roles +IF EXISTS (SELECT * FROM sys.database_principals WHERE name = 'FastTransfer_Executor' AND type = 'R') + PRINT '[OK] Role [FastTransfer_Executor] is created'; +ELSE + PRINT '[ERROR] Role [FastTransfer_Executor] is NOT created!'; + +IF EXISTS (SELECT * FROM sys.database_principals WHERE name = 'FastBCP_Executor' AND type = 'R') + PRINT '[OK] Role [FastBCP_Executor] is created'; +ELSE + PRINT '[ERROR] Role [FastBCP_Executor] is NOT created!'; + +PRINT ''; +PRINT '====================================================================='; +PRINT 'Next Steps'; +PRINT '====================================================================='; +PRINT '1. Add users to the executor roles:'; +PRINT ' ALTER ROLE [FastTransfer_Executor] ADD MEMBER [YourUserName];'; +PRINT ' ALTER ROLE [FastBCP_Executor] ADD MEMBER [YourUserName];'; +PRINT ''; +PRINT '2. Test the EncryptString function:'; +PRINT ' SELECT dbo.EncryptString(''TestPassword'');'; +PRINT ''; +PRINT '3. Run a test migration with FastTransfer:'; +PRINT ' EXEC dbo.xp_RunFastTransfer_secure @fastTransferDir = ''...'', ...'; +PRINT ''; +PRINT '4. Run a test export with FastBCP:'; +PRINT ' EXEC dbo.xp_RunFastBCP_secure @fastBCPDir = ''...'', ...'; +PRINT ''; +PRINT '====================================================================='; GO From 8e2846d015ccbe0ad6016a72f0af5f52ee9e4022 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Wed, 18 Mar 2026 09:46:58 +0100 Subject: [PATCH 34/37] fix: correction signature xp_RunFastBCP_secure pour correspondre au code C# MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Ajout de tous les paramètres manquants (outputFile, outputDirectory, usequotes, etc.) - Correction des noms de paramètres pour correspondre exactement à la signature C# - Ordre des paramètres respecté selon FastBCPWrapper_SP.cs.cs --- FastWrappers-TSQL.sql | 60 ++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/FastWrappers-TSQL.sql b/FastWrappers-TSQL.sql index 9cdcec7..6e58a72 100644 --- a/FastWrappers-TSQL.sql +++ b/FastWrappers-TSQL.sql @@ -161,39 +161,45 @@ END GO CREATE PROCEDURE [dbo].[xp_RunFastBCP_secure] - @fastBCPDir [nvarchar](max), - @sourceConnectionType [nvarchar](30), - @sourceConnectStringSecure [nvarchar](4000) = N'', - @sourceServer [nvarchar](255), - @sourceDSN [nvarchar](255) = N'', - @sourceProvider [nvarchar](1000) = N'', - @isSourceTrusted [bit] = 0, - @sourceUser [nvarchar](1000) = N'', - @sourcePasswordSecure [nvarchar](255) = N'', - @sourceDatabase [nvarchar](1000), + @fastBcpDir [nvarchar](max), + @connectionType [nvarchar](30), + @sourceConnectStringEnc [nvarchar](4000) = N'', + @sourcedsn [nvarchar](255) = N'', + @sourceprovider [nvarchar](1000) = N'', + @sourceserver [nvarchar](255) = N'', + @sourceuser [nvarchar](1000) = N'', + @sourcepasswordEnc [nvarchar](4000) = N'', + @trusted [bit] = 0, + @sourcedatabase [nvarchar](1000), @applicationintent [nvarchar](20) = N'ReadOnly', + @inputFile [nvarchar](4000) = N'', @query [nvarchar](4000) = N'', - @sourceSchema [nvarchar](255) = N'', - @sourceTable [nvarchar](255) = N'', - @targetFormat [nvarchar](50), - @targetPath [nvarchar](4000), - @targetFileName [nvarchar](500) = N'output', - @partitionSize [int] = 1048576, + @sourceschema [nvarchar](255) = N'', + @sourcetable [nvarchar](255) = N'', + @outputFile [nvarchar](4000) = N'', + @outputDirectory [nvarchar](4000) = N'', + @delimiter [nvarchar](10) = N'|', + @usequotes [bit] = 0, + @dateformat [nvarchar](50) = N'yyyy-MM-dd', + @encoding [nvarchar](50) = N'UTF-8', + @decimalseparator [nvarchar](2) = N',', + @parquetcompression [nvarchar](20) = N'zstd', + @degree [int] = -2, @method [nvarchar](50) = N'None', @distributeKeyColumn [nvarchar](255) = N'', - @degree [int] = 4, - @quotechar [nvarchar](2) = N'"', - @escapechar [nvarchar](2) = N'"', - @delimiter [nvarchar](10) = N',', - @decimalSeparator [nvarchar](2) = N'.', - @parquetcompression [nvarchar](20) = N'zstd', - @runId [nvarchar](255) = N'', - @settingsFile [nvarchar](4000) = N'', + @datadrivenquery [nvarchar](4000) = N'', + @mergeDistributedFile [bit] = 1, + @timestamped [bit] = 0, + @noheader [bit] = 0, + @boolformat [nvarchar](50) = N'automatic', + @runid [nvarchar](255) = N'', + @settingsfile [nvarchar](4000) = N'', @config [nvarchar](4000) = N'', - @debug [bit] = 0, - @nobanner [bit] = 0, + @cloudprofile [nvarchar](255) = N'', @license [nvarchar](4000) = N'', - @loglevel [nvarchar](50) = N'information' + @loglevel [nvarchar](50) = N'information', + @nobanner [bit] = 0, + @debug [bit] = 0 WITH EXECUTE AS CALLER AS EXTERNAL NAME [FastWrappers_TSQL].[FastWrapper.FastBCPCLR].[RunFastBCP_Secure]; GO From e4c60b2be3a355f690d18e91042c7c5cd8fbb072 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Wed, 18 Mar 2026 09:55:46 +0100 Subject: [PATCH 35/37] docs: update installation instructions and add additional options for FastWrappers-TSQL --- README.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d9febe0..cb2e766 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,52 @@ As a reminder : Download the latest release from the [Releases page](https://github.com/aetperf/FastWrappers-TSQL/releases). Each release provides 4 installation options: -1. **FastWrappers-TSQL.dacpac** - Data-tier Application Package (recommended for Visual Studio / SQL Server Data Tools) -2. **FastWrappers-TSQL.bacpac** - Binary Application Package (for import/export between servers) -3. **FastWrappers-TSQL.bak** - SQL Server Backup file (compatible with SQL Server 2016+, restore using SSMS) -4. **FastWrappers-TSQL.sql** - Pure SQL Script (execute using sqlcmd or SSMS) +### Recommended Installation Methods + +#### 1. **FastWrappers-TSQL.bak** (Recommended) +SQL Server Backup file - **Requires SQL Server 2019 or higher** + +✅ **Fastest installation method** +✅ **Pre-configured database with all objects** + +⚠️ **Post-installation configuration required:** +- Enable CLR integration (`sp_configure 'clr enabled', 1`) +- Trust the assembly using `sp_add_trusted_assembly` (see [Post-Installation Configuration](#post-installation-configuration)) + +**Installation:** +```sql +-- Restore the database +RESTORE DATABASE [FastWrappers-TSQL] +FROM DISK = 'C:\path\to\FastWrappers-TSQL.bak' +WITH MOVE 'FastWrappers-TSQL' TO 'C:\path\to\FastWrappers-TSQL.mdf', + MOVE 'FastWrappers-TSQL_log' TO 'C:\path\to\FastWrappers-TSQL_log.ldf'; +GO +``` + +#### 2. **FastWrappers-TSQL.sql** (Alternative for older SQL Server versions) +Self-contained SQL script - **Compatible with SQL Server 2016 or higher** + +✅ **Complete installation in a single script** +✅ **Includes database creation, CLR activation, trusted assembly configuration, and all objects** +✅ **No post-installation configuration needed** + +**Installation:** +```sql +-- Simply execute the script in SSMS or using sqlcmd +sqlcmd -S YourServer -i FastWrappers-TSQL.sql +``` + +**What's included:** +- Database creation with proper settings +- CLR integration enabled +- Assembly registration with `sp_add_trusted_assembly` (secure method) +- All stored procedures and functions +- Security roles (FastTransfer_Executor, FastBCP_Executor) + +### Additional Options + +3. **FastWrappers-TSQL.dacpac** - Data-tier Application Package (for Visual Studio / SQL Server Data Tools) +4. **FastWrappers-TSQL.bacpac** - Binary Application Package (for import/export between servers) ### Post-Installation Configuration From 3c6de7c8b479e9f7b829b19ba0ae7c9f03c2ae23 Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Thu, 2 Apr 2026 09:37:23 +0200 Subject: [PATCH 36/37] Remove DACPAC and BACPAC from release artifacts --- .github/workflows/release.yml | 99 ++++------------------------------- README.md | 9 +--- 2 files changed, 13 insertions(+), 95 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c37d624..377d7d6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,39 +13,6 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Setup MSBuild - uses: microsoft/setup-msbuild@v2 - - - name: Setup NuGet - uses: nuget/setup-nuget@v2 - - - name: Restore NuGet packages - run: nuget restore FastWrappers-TSQL.sln - - - name: Build SQL Project - run: msbuild FastWrappers_TSQL.sqlproj /p:Configuration=Release /p:Platform="Any CPU" /t:Build - - - name: Verify Build Artifacts - shell: powershell - run: | - Write-Host "Checking for build output..." - if (Test-Path "bin") { - Get-ChildItem -Path "bin" -Recurse -File | Format-Table FullName, Length - } else { - Write-Host "bin folder does not exist!" - } - - # Check for DACPAC in bin\Output (SQL Projects output here) - $dacpacPath = "bin\Output\FastWrappers_TSQL.dacpac" - if (Test-Path $dacpacPath) { - Write-Host "DACPAC found at: $dacpacPath" - } else { - Write-Host "DACPAC not found at: $dacpacPath" - Write-Host "Looking for .dacpac files..." - Get-ChildItem -Path . -Filter "*.dacpac" -Recurse -ErrorAction SilentlyContinue | Format-Table FullName - exit 1 - } - - name: Setup SQL Server (LocalDB) shell: powershell run: | @@ -56,17 +23,16 @@ jobs: # Wait for SQL Server to be ready Start-Sleep -Seconds 10 - - name: Deploy Database and Create Artifacts + - name: Create Database and Artifacts shell: powershell run: | # Variables $serverInstance = "(localdb)\MSSQLLocalDB" $dbName = "FastWrappers-TSQL" - $dacpacPath = "bin\Output\FastWrappers_TSQL.dacpac" $outputDir = "bin\Release" - $bacpacPath = "$outputDir\FastWrappers-TSQL.bacpac" $bakPath = "$outputDir\FastWrappers-TSQL.bak" $generatedSqlPath = "$outputDir\FastWrappers-TSQL.sql" + $templateSqlPath = "FastWrappers-TSQL.sql" # Ensure output directory exists if (!(Test-Path $outputDir)) { @@ -74,42 +40,18 @@ jobs: New-Item -Path $outputDir -ItemType Directory -Force | Out-Null } - # Verify DACPAC exists - if (!(Test-Path $dacpacPath)) { - Write-Error "DACPAC not found at: $dacpacPath" - exit 1 - } - - # Download SqlPackage if needed - if (!(Test-Path "SqlPackage\SqlPackage.exe")) { - Write-Host "Downloading SqlPackage..." - Invoke-WebRequest -Uri "https://aka.ms/sqlpackage-windows" -OutFile "SqlPackage.zip" - Expand-Archive -Path "SqlPackage.zip" -DestinationPath "SqlPackage" -Force - Remove-Item "SqlPackage.zip" - } - - $sqlPackage = "SqlPackage\SqlPackage.exe" - - # Deploy the DACPAC to create the database - Write-Host "Deploying DACPAC to create database..." - & $sqlPackage /Action:Publish /SourceFile:$dacpacPath /TargetServerName:$serverInstance /TargetDatabaseName:$dbName /p:IncludeCompositeObjects=True + # Create database from template SQL file + Write-Host "Creating database from SQL template..." + sqlcmd -S $serverInstance -i $templateSqlPath if ($LASTEXITCODE -ne 0) { - Write-Error "Failed to deploy DACPAC" + Write-Error "Failed to create database from SQL template" exit 1 } - # Wait for deployment to complete + # Wait for database creation to complete Start-Sleep -Seconds 5 - # Change database owner to 'sa' (required for signed UNSAFE assemblies to load properly) - Write-Host "Setting database owner to sa..." - sqlcmd -S $serverInstance -d $dbName -Q "EXEC sp_changedbowner 'sa'" - - # Enable CLR for testing - Write-Host "Enabling CLR..." - sqlcmd -S $serverInstance -Q "EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'clr enabled', 1; RECONFIGURE;" - # Test the assembly Write-Host "Testing assembly..." $testResult = sqlcmd -S $serverInstance -d $dbName -Q "SELECT dbo.EncryptString('test') AS Result" 2>&1 @@ -122,14 +64,6 @@ jobs: Write-Warning "Continuing with artifact creation..." } - # Export to BACPAC - Write-Host "Exporting to BACPAC..." - & $sqlPackage /Action:Export /SourceServerName:$serverInstance /SourceDatabaseName:$dbName /TargetFile:$bacpacPath - - if ($LASTEXITCODE -ne 0) { - Write-Warning "Failed to create BACPAC, continuing..." - } - # Create backup file Write-Host "Creating SQL Server backup..." $bakFullPath = Join-Path $PWD $bakPath @@ -165,7 +99,7 @@ jobs: if ($assemblyHex) { # Read template and inject assembly binary - $sqlTemplate = Get-Content "FastWrappers-TSQL.sql" -Raw + $sqlTemplate = Get-Content $templateSqlPath -Raw $finalSql = $sqlTemplate -replace '__ASSEMBLY_FROM_0X__', $assemblyHex $finalSql | Out-File -FilePath $generatedSqlPath -Encoding UTF8 Write-Host "SQL script generated successfully" @@ -173,10 +107,6 @@ jobs: Write-Warning "Failed to extract assembly binary" } - # Copy DACPAC with proper name - Write-Host "Copying DACPAC with release name..." - Copy-Item $dacpacPath "$outputDir\FastWrappers-TSQL.dacpac" -Force - # List all created artifacts Write-Host "`nCreated artifacts:" Get-ChildItem -Path $outputDir -File | Format-Table Name, Length @@ -196,8 +126,6 @@ jobs: # Copy available files $files = @( - @{Source="bin\Release\FastWrappers-TSQL.dacpac"; Name="FastWrappers-TSQL.dacpac"}, - @{Source="bin\Release\FastWrappers-TSQL.bacpac"; Name="FastWrappers-TSQL.bacpac"}, @{Source="bin\Release\FastWrappers-TSQL.bak"; Name="FastWrappers-TSQL.bak"}, @{Source="bin\Release\FastWrappers-TSQL.sql"; Name="FastWrappers-TSQL.sql"} ) @@ -224,8 +152,6 @@ jobs: ### Installation Files - - **FastWrappers-TSQL.dacpac** - Data-tier Application Package (for Visual Studio / SQL Server Data Tools) - - **FastWrappers-TSQL.bacpac** - Binary Application Package (for import/export between servers) - **FastWrappers-TSQL.bak** - SQL Server Backup (restore using SSMS) - **FastWrappers-TSQL.sql** - SQL Script (execute using sqlcmd or SSMS) @@ -258,13 +184,10 @@ jobs: SELECT dbo.EncryptString('test'); ``` - **Option 2: Deploy DACPAC** - Use SqlPackage or Visual Studio to deploy the .dacpac file, then run: + **Option 2: Execute SQL Script (.sql file)** ```sql - USE [FastWrappers-TSQL]; - GO - EXEC sp_changedbowner 'sa'; - GO + -- Simply execute the script in SSMS or using sqlcmd + sqlcmd -S YourServer -i FastWrappers-TSQL.sql ``` ### Usage diff --git a/README.md b/README.md index cb2e766..68782e8 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ As a reminder : ## Installation -Download the latest release from the [Releases page](https://github.com/aetperf/FastWrappers-TSQL/releases). Each release provides 4 installation options: +Download the latest release from the [Releases page](https://github.com/aetperf/FastWrappers-TSQL/releases). Each release provides 2 installation options: -### Recommended Installation Methods +### Installation Methods #### 1. **FastWrappers-TSQL.bak** (Recommended) SQL Server Backup file - **Requires SQL Server 2019 or higher** @@ -51,11 +51,6 @@ sqlcmd -S YourServer -i FastWrappers-TSQL.sql - All stored procedures and functions - Security roles (FastTransfer_Executor, FastBCP_Executor) -### Additional Options - -3. **FastWrappers-TSQL.dacpac** - Data-tier Application Package (for Visual Studio / SQL Server Data Tools) -4. **FastWrappers-TSQL.bacpac** - Binary Application Package (for import/export between servers) - ### Post-Installation Configuration After restoring the database (especially from .bak), you **must** configure CLR integration. Two options are available depending on your environment: From 2e8e87a4c874b1ba07b94257a7fd45f0d84d65ad Mon Sep 17 00:00:00 2001 From: PierreAntoineAP Date: Thu, 2 Apr 2026 09:40:49 +0200 Subject: [PATCH 37/37] Fix: Restore build steps to generate assembly for .sql artifact --- .github/workflows/release.yml | 62 +++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 377d7d6..7ebee23 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,6 +13,39 @@ jobs: - name: Checkout code uses: actions/checkout@v4 + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v2 + + - name: Setup NuGet + uses: nuget/setup-nuget@v2 + + - name: Restore NuGet packages + run: nuget restore FastWrappers-TSQL.sln + + - name: Build SQL Project + run: msbuild FastWrappers_TSQL.sqlproj /p:Configuration=Release /p:Platform="Any CPU" /t:Build + + - name: Verify Build Artifacts + shell: powershell + run: | + Write-Host "Checking for build output..." + if (Test-Path "bin") { + Get-ChildItem -Path "bin" -Recurse -File | Format-Table FullName, Length + } else { + Write-Host "bin folder does not exist!" + } + + # Check for DACPAC in bin\Output (SQL Projects output here) + $dacpacPath = "bin\Output\FastWrappers_TSQL.dacpac" + if (Test-Path $dacpacPath) { + Write-Host "DACPAC found at: $dacpacPath" + } else { + Write-Host "DACPAC not found at: $dacpacPath" + Write-Host "Looking for .dacpac files..." + Get-ChildItem -Path . -Filter "*.dacpac" -Recurse -ErrorAction SilentlyContinue | Format-Table FullName + exit 1 + } + - name: Setup SQL Server (LocalDB) shell: powershell run: | @@ -23,12 +56,13 @@ jobs: # Wait for SQL Server to be ready Start-Sleep -Seconds 10 - - name: Create Database and Artifacts + - name: Deploy Database and Create Artifacts shell: powershell run: | # Variables $serverInstance = "(localdb)\MSSQLLocalDB" $dbName = "FastWrappers-TSQL" + $dacpacPath = "bin\Output\FastWrappers_TSQL.dacpac" $outputDir = "bin\Release" $bakPath = "$outputDir\FastWrappers-TSQL.bak" $generatedSqlPath = "$outputDir\FastWrappers-TSQL.sql" @@ -40,16 +74,32 @@ jobs: New-Item -Path $outputDir -ItemType Directory -Force | Out-Null } - # Create database from template SQL file - Write-Host "Creating database from SQL template..." - sqlcmd -S $serverInstance -i $templateSqlPath + # Verify DACPAC exists + if (!(Test-Path $dacpacPath)) { + Write-Error "DACPAC not found at: $dacpacPath" + exit 1 + } + + # Download SqlPackage if needed + if (!(Test-Path "SqlPackage\SqlPackage.exe")) { + Write-Host "Downloading SqlPackage..." + Invoke-WebRequest -Uri "https://aka.ms/sqlpackage-windows" -OutFile "SqlPackage.zip" + Expand-Archive -Path "SqlPackage.zip" -DestinationPath "SqlPackage" -Force + Remove-Item "SqlPackage.zip" + } + + $sqlPackage = "SqlPackage\SqlPackage.exe" + + # Deploy the DACPAC to create the database + Write-Host "Deploying DACPAC to create database..." + & $sqlPackage /Action:Publish /SourceFile:$dacpacPath /TargetServerName:$serverInstance /TargetDatabaseName:$dbName /p:IncludeCompositeObjects=True if ($LASTEXITCODE -ne 0) { - Write-Error "Failed to create database from SQL template" + Write-Error "Failed to deploy DACPAC" exit 1 } - # Wait for database creation to complete + # Wait for deployment to complete Start-Sleep -Seconds 5 # Test the assembly