From 07ed45eab2bdfa3a1e316bfeb9f1ae5faa6a222a Mon Sep 17 00:00:00 2001 From: Khushi Kathuria Date: Tue, 9 Dec 2025 11:17:34 +0530 Subject: [PATCH 1/6] impl(bq_driver): Migration sripts --- ci/migration/migrate_dsn.ps1 | 208 +++++++++++++++++++++++ ci/migration/migrate_dsn.sh | 311 +++++++++++++++++++++++++++++++++++ 2 files changed, 519 insertions(+) create mode 100644 ci/migration/migrate_dsn.ps1 create mode 100644 ci/migration/migrate_dsn.sh diff --git a/ci/migration/migrate_dsn.ps1 b/ci/migration/migrate_dsn.ps1 new file mode 100644 index 0000000000..a2b3bd2198 --- /dev/null +++ b/ci/migration/migrate_dsn.ps1 @@ -0,0 +1,208 @@ +<# +Migration script for Windows ODBC DSNs +- Migrates from "Simba ODBC Driver for Google Bigquery" +- to "Google Bigquery Driver" + +Usage: + migrate.ps1 -Mode copy -DriverInstaller "GoogleBigQueryODBC.msi" + migrate.ps1 -Mode replace -DriverInstaller "GoogleBigQueryODBC.msi" +#> + +param( + [Parameter(Mandatory=$true)] + [ValidateSet("copy","replace")] + [string]$Mode, + + [Parameter(Mandatory=$true)] + [string]$DriverInstaller +) + +$SimbaDriverName = "Simba ODBC Driver for Google Bigquery" +$GoogleDriverName = "Google Bigquery Driver" + +Write-Host "=== Installing Google Bigquery Driver ===" +Start-Process "msiexec.exe" -ArgumentList "/i `"$DriverInstaller`" /quiet /norestart" -Wait +Write-Host "=== Driver installation complete ===`n" + +# Registry paths for DSNs +$DSNRoots = @( + "HKLM:\SOFTWARE\ODBC\ODBC.INI", + "HKCU:\SOFTWARE\ODBC\ODBC.INI" +) +$DSNListRoot = "ODBC Data Sources" + +function CopyRegistryTree($SourcePath, $TargetPath) { + if (!(Test-Path $TargetPath)) { + New-Item -Path $TargetPath | Out-Null + } + + $props = Get-ItemProperty -Path $SourcePath + foreach ($p in $props.PSObject.Properties) { + if ($p.Name -notlike "PS*") { + Set-ItemProperty -Path $TargetPath -Name $p.Name -Value $p.Value + } + } +} + +# === DPAPI HEX DECRYPTOR === +function Decode-DPAPIHex($hex) { + if ([string]::IsNullOrWhiteSpace($hex)) { return $null } + + Add-Type -AssemblyName System.Security + + # Convert hexadecimal → byte array + $bytes = for ($i = 0; $i -lt $hex.Length; $i += 2) { + [Convert]::ToByte($hex.Substring($i, 2), 16) + } + + # Try LocalMachine first + try { + return [System.Security.Cryptography.ProtectedData]::Unprotect( + $bytes, $null, + [System.Security.Cryptography.DataProtectionScope]::LocalMachine + ) + } + catch { + # Try CurrentUser if LocalMachine does not work + return [System.Security.Cryptography.ProtectedData]::Unprotect( + $bytes, $null, + [System.Security.Cryptography.DataProtectionScope]::CurrentUser + ) + } +} + +function TestODBCConnection($DSN) { + Write-Host " → Testing ODBC connection..." + try { + $conn = New-Object System.Data.Odbc.OdbcConnection("DSN=$DSN") + $conn.Open() + Write-Host " → Connection test: OK" -ForegroundColor Green + $conn.Close() + } catch { + Write-Host " → Connection test: FAILED" -ForegroundColor Red + Write-Host $_.Exception.Message + } +} +$SimbaDSNs = @() + +foreach ($root in $DSNRoots) { + + $dsnTablePath = Join-Path $root $DSNListRoot + if (!(Test-Path $dsnTablePath)) { continue } + + $dsns = Get-ItemProperty $dsnTablePath + foreach ($entry in $dsns.PSObject.Properties) { + + $dsnName = $entry.Name + $driverValue = $entry.Value + + if ($driverValue -eq $SimbaDriverName) { + $SimbaDSNs += [PSCustomObject]@{ + Root = $root + DsnName = $dsnName + DsnTablePath = $dsnTablePath + } + } + } +} + +if ($SimbaDSNs.Count -eq 0) { + Write-Host "No Simba DSNs found. Nothing to migrate." + exit +} +elseif ($SimbaDSNs.Count -eq 1) { + $Chosen = $SimbaDSNs[0] +} +else { + Write-Host "`nMultiple Simba DSNs found:" + for ($i=0; $i -lt $SimbaDSNs.Count; $i++) { + Write-Host " [$($i+1)] $($SimbaDSNs[$i].DsnName) ($($SimbaDSNs[$i].Root))" + } + + do { + $sel = Read-Host "Enter the number of the DSN you want to migrate" + } until ($sel -as [int] -and $sel -ge 1 -and $sel -le $SimbaDSNs.Count) + + $Chosen = $SimbaDSNs[$sel - 1] +} + +Write-Host "`nSelected DSN: $($Chosen.DsnName)" +Write-Host "Location: $($Chosen.Root)`n" + +# =============================================================== +# === Continue the original loop logic ONLY for chosen DSN === +# =============================================================== + +$root = $Chosen.Root +$dsnName = $Chosen.DsnName +$dsnTablePath = $Chosen.DsnTablePath + +Write-Host "`nFound Simba DSN: $dsnName" + +# Source DSN registry key +$srcDSNKey = Join-Path $root $dsnName +if (!(Test-Path $srcDSNKey)) { + Write-Warning "DSN entry exists in table but no registry key: $srcDSNKey" + exit +} + +# Determine target DSN values based on mode +if ($Mode -eq "replace") { + $newDSNName = $dsnName +} else { + $newDSNName = "${dsnName}_Google" +} + +Write-Host " → Target DSN: $newDSNName" +$dstDSNKey = Join-Path $root $newDSNName + +# 1. Update ODBC Data Sources table +Set-ItemProperty -Path $dsnTablePath -Name $newDSNName -Value $GoogleDriverName +if ($Mode -eq "replace" -and $newDSNName -eq $dsnName) { + Set-ItemProperty -Path $dsnTablePath -Name $dsnName -Value $GoogleDriverName +} + +# 2. Copy registry values +CopyRegistryTree -SourcePath $srcDSNKey -TargetPath $dstDSNKey + +# 3. Update Driver DLL +$googleDriverKey = Get-ChildItem "HKLM:\SOFTWARE\ODBC\ODBCINST.INI" | + Where-Object { $_.PSChildName -eq $GoogleDriverName } +if (!$googleDriverKey) { Write-Warning "Google driver not found in ODBCINST.INI"; exit } + +$googleDLL = (Get-ItemProperty $googleDriverKey.PSPath).Driver +Set-ItemProperty -Path $dstDSNKey -Name "Driver" -Value $googleDLL +Write-Host " → Set Driver DLL to: $googleDLL" + +# 3b. Fix TrustedCerts +$driverFolder = Split-Path $googleDLL -Parent +$rootsCert = Join-Path $driverFolder "Assets\roots.pem" +if (Test-Path $rootsCert) { + Set-ItemProperty -Path $dstDSNKey -Name "TrustedCerts" -Value $rootsCert + Write-Host " → Updated TrustedCerts to: $rootsCert" +} else { + Write-Warning " → roots.pem not found in $driverFolder\Assets" +} + +# 4. Decrypt KeyFilePath_Enc +$encKeyPath = (Get-ItemProperty $srcDSNKey -ErrorAction SilentlyContinue).KeyFilePath_Enc +if ($encKeyPath) { + + Write-Host " → Decrypting KeyFilePath_Enc..." + + $rawBytes = Decode-DPAPIHex $encKeyPath + if ($rawBytes) { + $plainPath = [System.Text.Encoding]::UTF8.GetString($rawBytes) + Write-Host " → Decrypted KeyFilePath: $plainPath" + + # Write plain KeyFilePath into new DSN + Set-ItemProperty -Path $dstDSNKey -Name "KeyFilePath" -Value $plainPath + } else { + Write-Warning " → Failed to decrypt KeyFilePath_Enc" + } + } + + # 5. Test DSN connectivity + TestODBCConnection -DSN $newDSNName + +Write-Host "`n=== Migration complete ===" diff --git a/ci/migration/migrate_dsn.sh b/ci/migration/migrate_dsn.sh new file mode 100644 index 0000000000..7faf9beb24 --- /dev/null +++ b/ci/migration/migrate_dsn.sh @@ -0,0 +1,311 @@ +# Migration script for Linux/MacOS ODBC DSNs +# - Migrates from "Simba Google BigQuery ODBC Connector" +# - to "Google ODBC Driver for Google BigQuery" + +# Usage: +# migrate.sh copy +# migrate.sh replace + +#!/bin/bash +set -euo pipefail + +usage() { + cat < + mode: copy - create new DSN(s) named _google (originals untouched) + replace - update existing Simba DSN(s) in-place (name preserved) + installer-path: directory OR .zip OR .tar.gz/.tgz +Environment: + ODBCINI - optional path to odbc.ini. If not set, /etc/odbc.ini is used. +EOF + exit 1 +} + +if [ $# -ne 2 ]; then + usage +fi + +MODE="$1" +INSTALLER="$2" + +if [ "$MODE" != "copy" ] && [ "$MODE" != "replace" ]; then + echo "ERROR: mode must be 'copy' or 'replace'" + exit 1 +fi + +# Resolve odbc.ini location (env first, then /etc/odbc.ini) +if [ -n "${ODBCINI-}" ]; then + ODBCINI_PATH="$ODBCINI" +elif [ -f "/etc/odbc.ini" ]; then + ODBCINI_PATH="/etc/odbc.ini" +else + echo "ERROR: No odbc.ini found. Set ODBCINI env var or ensure /etc/odbc.ini exists." + exit 1 +fi + +if [ ! -f "$ODBCINI_PATH" ]; then + echo "ERROR: odbc.ini not found at resolved path: $ODBCINI_PATH" + exit 1 +fi + +echo "Using odbc.ini: $ODBCINI_PATH" +echo "Mode: $MODE" +echo "Installer input: $INSTALLER" + +WORKDIR="" +CLEANUP=0 + +# Prepare installer extraction if necessary +if [ -d "$INSTALLER" ]; then + echo "Installer is a directory: $INSTALLER" + WORKDIR="$(realpath "$INSTALLER")" +else + WORKDIR="$(mktemp -d)" + CLEANUP=1 + case "$INSTALLER" in + *.zip) + if ! command -v unzip >/dev/null 2>&1; then + echo "ERROR: unzip is required to extract zip archives." + exit 1 + fi + unzip -q "$INSTALLER" -d "$WORKDIR" + ;; + *.tar.gz | *.tgz) + tar -xzf "$INSTALLER" -C "$WORKDIR" + ;; + *) + echo "ERROR: Installer must be a directory, .zip, or .tar.gz/.tgz" + exit 1 + ;; + esac +fi + +# Find lib/ folder in extracted tree +LIBDIR="" +if [ -d "$WORKDIR/lib" ]; then + LIBDIR="$WORKDIR/lib" +else + LIBDIR="$(find "$WORKDIR" -type d -name lib | head -n 1 || true)" +fi + +if [ -z "$LIBDIR" ] || [ ! -d "$LIBDIR" ]; then + echo "ERROR: Could not find lib/ folder inside installer content." + [ "$CLEANUP" -eq 1 ] && rm -rf "$WORKDIR" + exit 1 +fi + +# Find driver file (prefer .so, else .dylib) +NEW_DRIVER_SRC="$(find "$LIBDIR" -maxdepth 1 -type f -name "*.so" -print -quit || true)" +if [ -z "$NEW_DRIVER_SRC" ]; then + NEW_DRIVER_SRC="$(find "$LIBDIR" -maxdepth 1 -type f -name "*.dylib" -print-quit || true)" +fi + +if [ -z "$NEW_DRIVER_SRC" ]; then + echo "ERROR: No .so or .dylib found in $LIBDIR" + [ "$CLEANUP" -eq 1 ] && rm -rf "$WORKDIR" + exit 1 +fi + +echo "Found driver in installer: $NEW_DRIVER_SRC" + +DEST_DIR="/usr/local/lib/google_odbc" +mkdir -p "$DEST_DIR" +DRIVER_BASENAME="$(basename "$NEW_DRIVER_SRC")" +DEST_DRIVER_PATH="$DEST_DIR/$DRIVER_BASENAME" + +if [ ! -w "$DEST_DIR" ]; then + echo "Copying driver to $DEST_DIR with sudo..." + sudo cp -f "$NEW_DRIVER_SRC" "$DEST_DRIVER_PATH" + sudo chmod 644 "$DEST_DRIVER_PATH" +else + cp -f "$NEW_DRIVER_SRC" "$DEST_DRIVER_PATH" + chmod 644 "$DEST_DRIVER_PATH" +fi + +echo "Driver copied to: $DEST_DRIVER_PATH" + +TS="$(date +%Y%m%d%H%M%S)" +ODBC_BAK="${ODBCINI_PATH}.bak.${TS}" +cp -a "$ODBCINI_PATH" "$ODBC_BAK" +echo "Backup of odbc.ini saved to: $ODBC_BAK" + +# Detect Simba DSNs in [ODBC Data Sources] +SIMBA_DSNS=() +while IFS= read -r line; do + trimmed="$(echo "$line" | sed -e 's/^[ \t]*//' -e 's/[ \t]*$//')" + if [[ "$trimmed" == *=*Simba\ Google\ BigQuery\ ODBC\ Connector* ]]; then + name="${trimmed%%=*}" + SIMBA_DSNS+=("$name") + fi +done < <(awk '/^\[ODBC Data Sources\]/{flag=1; next} /^\[/{flag=0} flag{print}' "$ODBCINI_PATH" || true) + +echo "Detected Simba DSN(s): ${SIMBA_DSNS[*]}" + +############################################################################## +# ★★★ MINIMAL CHANGE: Ask user which DSN to migrate if multiple exist ★★★ +############################################################################## +if [ ${#SIMBA_DSNS[@]} -eq 0 ]; then + echo "No Simba DSNs found. Exiting." + [ "$CLEANUP" -eq 1 ] && rm -rf "$WORKDIR" + exit 0 + +elif [ ${#SIMBA_DSNS[@]} -eq 1 ]; then + SELECTED_DSN="${SIMBA_DSNS[0]}" + +else + echo "Multiple Simba DSNs detected:" + i=1 + for d in "${SIMBA_DSNS[@]}"; do + echo " $i) $d" + i=$((i + 1)) + done + + while true; do + read -rp "Select the DSN to migrate: " choice + if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le ${#SIMBA_DSNS[@]} ]; then + SELECTED_DSN="${SIMBA_DSNS[$((choice - 1))]}" + break + fi + echo "Invalid selection. Try again." + done +fi + +echo "Selected DSN: $SELECTED_DSN" + +# Override the array so downstream code behaves unchanged +SIMBA_DSNS=("$SELECTED_DSN") +############################################################################## + +TMP_ODBC="$(mktemp)" +cp "$ODBCINI_PATH" "$TMP_ODBC" + +# Replace driver & description inside a DSN section +update_dsn_inplace() { + target="$1" + newdrv="$2" + newdesc="$3" + awk -v section="$target" -v drv="$newdrv" -v desc="$newdesc" ' + BEGIN { in_section=0 } + { + if ($0 ~ ("^\\[" section "\\]$")) { print; in_section=1; next } + if ($0 ~ /^\[/ && in_section==1) { in_section=0 } + if (in_section==1) { + if ($0 ~ /^Description=/) { print "Description=" desc; next } + if ($0 ~ /^Driver=/) { print "Driver=" drv; next } + } + print + } + ' "$TMP_ODBC" >"${TMP_ODBC}.new" && mv "${TMP_ODBC}.new" "$TMP_ODBC" +} + +create_dsn_copy() { + orig="$1" + copyname="${orig}_google" + newdrv="$2" + newdesc="$3" + + if awk -v s="[$copyname]" 'BEGIN{found=0} $0==s{found=1} END{exit !found}' "$TMP_ODBC"; then + echo "Note: $copyname already exists; skipping creation." + return + fi + + awk -v s="[$orig]" 'BEGIN{in=0} { + if($0==s){in=1; print; next} + if(in==1 && $0~/^\[/){exit} + if(in==1) print + }' "$TMP_ODBC" >"${TMP_ODBC}.${orig}.section" || true + + if [ ! -s "${TMP_ODBC}.${orig}.section" ]; then + echo "Warning: Original section [$orig] not found; creating minimal section for $copyname" + { + echo "[$copyname]" + echo "Description=$newdesc" + echo "Driver=$newdrv" + } >>"$TMP_ODBC" + return + fi + + awk -v orig="$orig" -v copy="$copyname" -v drv="$newdrv" -v desc="$newdesc" ' + NR==1{ + if($0 ~ ("^\\[" orig "\\]$")){print "[" copy "]"} else {print} + next + } + { + if($0 ~ /^Description=/){ print "Description=" desc; next } + if($0 ~ /^Driver=/){ print "Driver=" drv; next } + print + }' "${TMP_ODBC}.${orig}.section" >>"$TMP_ODBC" + + rm -f "${TMP_ODBC}.${orig}.section" + echo "Created DSN copy: [$copyname]" +} + +NEW_DESC="Google ODBC Driver for Google BigQuery DSN" +NEW_DRV="$DEST_DRIVER_PATH" +NEW_DRIVER_NAME="Google ODBC Driver for Google BigQuery" + +# Update DSNs +for dsn in "${SIMBA_DSNS[@]}"; do + if [ "$MODE" = "replace" ]; then + awk -v dsn="$dsn" -v newname="$NEW_DRIVER_NAME" ' + BEGIN { in_ods=0 } + { + if ($0 ~ /^\[ODBC Data Sources\]/){ print; in_ods=1; next } + if ($0 ~ /^\[/ && $0 !~ /^\[ODBC Data Sources\]/){ in_ods=0 } + if(in_ods==1){ + if($0 ~ ("^"dsn"[ \t]*=")){ + print dsn "=" newname + next + } + } + print + }' "$TMP_ODBC" >"${TMP_ODBC}.tmp" && mv "${TMP_ODBC}.tmp" "$TMP_ODBC" + + update_dsn_inplace "$dsn" "$NEW_DRV" "$NEW_DESC" + echo "Replaced DSN: [$dsn]" + + else + create_dsn_copy "$dsn" "$NEW_DRV" "$NEW_DESC" + newdsn="${dsn}_google" + + awk -v original="$dsn" -v addeddsn="$newdsn" -v newname="$NEW_DRIVER_NAME" ' + BEGIN{ in_ods=0; printed=0 } + { + if($0 ~ /^\[ODBC Data Sources\]/){ print; in_ods=1; next } + if($0 ~ /^\[/ && $0 !~ /^\[ODBC Data Sources\]/){ + if(in_ods==1 && printed==0){ + print addeddsn "=" newname + printed=1 + } + in_ods=0 + } + if(in_ods==1){ print; next } + print + } + END{ + if(in_ods==1 && printed==0) print addeddsn "=" newname + } + ' "$TMP_ODBC" >"${TMP_ODBC}.tmp" && mv "${TMP_ODBC}.tmp" "$TMP_ODBC" + + echo "Created DSN copy: [$newdsn]" + fi +done + +# Write output back +if [ -w "$ODBCINI_PATH" ]; then + mv "$TMP_ODBC" "$ODBCINI_PATH" +else + echo "Updating $ODBCINI_PATH with sudo..." + sudo mv "$TMP_ODBC" "$ODBCINI_PATH" + sudo chown root:root "$ODBCINI_PATH" || true + sudo chmod 644 "$ODBCINI_PATH" || true +fi + +echo "Updated odbc.ini successfully: $ODBCINI_PATH" +echo "Backup retained at: $ODBC_BAK" +echo "Driver in use: $NEW_DRV" +echo "Mode finished: $MODE" + +[ "$CLEANUP" -eq 1 ] && rm -rf "$WORKDIR" + +exit 0 From 643073401205e3f17c2193c3a8d3a076f410aa71 Mon Sep 17 00:00:00 2001 From: Khushi Kathuria Date: Tue, 9 Dec 2025 11:23:50 +0530 Subject: [PATCH 2/6] impl(bq_driver): Migration sripts --- ci/migration/migrate_dsn.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/migration/migrate_dsn.sh b/ci/migration/migrate_dsn.sh index 7faf9beb24..f37bb5ab34 100644 --- a/ci/migration/migrate_dsn.sh +++ b/ci/migration/migrate_dsn.sh @@ -1,3 +1,4 @@ +#!/bin/bash # Migration script for Linux/MacOS ODBC DSNs # - Migrates from "Simba Google BigQuery ODBC Connector" # - to "Google ODBC Driver for Google BigQuery" @@ -6,7 +7,6 @@ # migrate.sh copy # migrate.sh replace -#!/bin/bash set -euo pipefail usage() { From d7a806e988eb181679586442e8cc44e972293963 Mon Sep 17 00:00:00 2001 From: Sachin Purohit Date: Tue, 9 Dec 2025 15:04:12 +0000 Subject: [PATCH 3/6] chore: added license --- ci/migration/migrate_dsn.ps1 | 17 +++++++++++++++++ ci/migration/migrate_dsn.sh | 15 +++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/ci/migration/migrate_dsn.ps1 b/ci/migration/migrate_dsn.ps1 index a2b3bd2198..3b779e76ed 100644 --- a/ci/migration/migrate_dsn.ps1 +++ b/ci/migration/migrate_dsn.ps1 @@ -1,3 +1,20 @@ +# !/usr/bin/env powershell +# +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + <# Migration script for Windows ODBC DSNs - Migrates from "Simba ODBC Driver for Google Bigquery" diff --git a/ci/migration/migrate_dsn.sh b/ci/migration/migrate_dsn.sh index f37bb5ab34..1c1e7cea0c 100644 --- a/ci/migration/migrate_dsn.sh +++ b/ci/migration/migrate_dsn.sh @@ -1,4 +1,19 @@ #!/bin/bash +# +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # Migration script for Linux/MacOS ODBC DSNs # - Migrates from "Simba Google BigQuery ODBC Connector" # - to "Google ODBC Driver for Google BigQuery" From cd70326dae660a4b9ab86b2d27d1df5061bb503f Mon Sep 17 00:00:00 2001 From: Khushi Kathuria Date: Fri, 12 Dec 2025 12:30:33 +0530 Subject: [PATCH 4/6] impl(bq_driver): Changes --- ci/migration/migrate_dsn.ps1 | 6 +++--- ci/migration/migrate_dsn.sh | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ci/migration/migrate_dsn.ps1 b/ci/migration/migrate_dsn.ps1 index 3b779e76ed..a5477cb2b8 100644 --- a/ci/migration/migrate_dsn.ps1 +++ b/ci/migration/migrate_dsn.ps1 @@ -18,7 +18,7 @@ <# Migration script for Windows ODBC DSNs - Migrates from "Simba ODBC Driver for Google Bigquery" -- to "Google Bigquery Driver" +- to "ODBC Driver for BigQuery" Usage: migrate.ps1 -Mode copy -DriverInstaller "GoogleBigQueryODBC.msi" @@ -35,9 +35,9 @@ param( ) $SimbaDriverName = "Simba ODBC Driver for Google Bigquery" -$GoogleDriverName = "Google Bigquery Driver" +$GoogleDriverName = "ODBC Driver for BigQuery" -Write-Host "=== Installing Google Bigquery Driver ===" +Write-Host "=== Installing ODBC Driver for BigQuery ===" Start-Process "msiexec.exe" -ArgumentList "/i `"$DriverInstaller`" /quiet /norestart" -Wait Write-Host "=== Driver installation complete ===`n" diff --git a/ci/migration/migrate_dsn.sh b/ci/migration/migrate_dsn.sh index 1c1e7cea0c..7a12a1aedd 100644 --- a/ci/migration/migrate_dsn.sh +++ b/ci/migration/migrate_dsn.sh @@ -16,7 +16,7 @@ # Migration script for Linux/MacOS ODBC DSNs # - Migrates from "Simba Google BigQuery ODBC Connector" -# - to "Google ODBC Driver for Google BigQuery" +# - to "ODBC Driver for BigQuery" # Usage: # migrate.sh copy @@ -255,9 +255,9 @@ create_dsn_copy() { echo "Created DSN copy: [$copyname]" } -NEW_DESC="Google ODBC Driver for Google BigQuery DSN" +NEW_DESC="ODBC Driver for BigQuery DSN" NEW_DRV="$DEST_DRIVER_PATH" -NEW_DRIVER_NAME="Google ODBC Driver for Google BigQuery" +NEW_DRIVER_NAME="ODBC Driver for BigQuery" # Update DSNs for dsn in "${SIMBA_DSNS[@]}"; do From 01fced3577546cb2f14ffb93730437633b51d82e Mon Sep 17 00:00:00 2001 From: Khushi Kathuria Date: Thu, 18 Dec 2025 12:21:48 +0530 Subject: [PATCH 5/6] impl(bq_driver): Add README file --- ci/migration/README.md | 249 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 ci/migration/README.md diff --git a/ci/migration/README.md b/ci/migration/README.md new file mode 100644 index 0000000000..544afc5022 --- /dev/null +++ b/ci/migration/README.md @@ -0,0 +1,249 @@ +# Cross‑Platform ODBC DSN Migration Scripts (Windows / Linux / macOS) + +This repository provides **cross‑platform migration scripts** to move existing BigQuery ODBC DSNs from legacy **Simba drivers** to the new **ODBC Driver for BigQuery**. + +The scripts support: + +* **Windows** (PowerShell) +* **Linux** (Bash) +* **macOS** (Bash) + +They follow the **same high‑level behavior and migration semantics** across all platforms, with platform‑specific implementation details. + +--- + +## Goals of the Migration + +* Seamlessly transition DSNs from Simba BigQuery drivers to the Google‑provided ODBC Driver for BigQuery +* Preserve existing DSN configuration wherever possible +* Support **safe testing (copy mode)** and **in‑place migration (replace mode)** +* Minimize manual registry / config file editing + +--- + +## What the Script Does + +At a high level, the script performs the following steps: + +1. **Installs the new ODBC Driver for BigQuery** . +2. **Searches for existing DSNs** that use the legacy Simba BigQuery driver. +3. **Prompts the user to select a DSN** if multiple Simba-based DSNs are found. +4. **Migrates the selected DSN** based on the chosen migration mode (`copy` or `replace`). +5. **Updates registry entries for Windows** so the DSN points to the new Google BigQuery ODBC driver. +6. **Decrypts and migrates encrypted credentials** (if present). +7. **Tests the migrated DSN connection** at the end. + +--- + +## Supported Drivers + +| Platform | Legacy Driver Detected | Target Driver | +| ------------- | ------------------------------------- | ------------------------ | +| Windows | Simba ODBC Driver for Google BigQuery | ODBC Driver for BigQuery | +| Linux / macOS | Simba Google BigQuery ODBC Connector | ODBC Driver for BigQuery | + +--- + +## Migration Modes (All Platforms) + +Both scripts support the same two explicit modes. + +### 1. `copy` Mode (Recommended for first run) + +**Behavior:** + +* Original Simba DSN is **left unchanged** +* A **new DSN is created** using the Google driver +* New DSN name is derived automatically + +| Original DSN | New DSN | +| ------------ | ------------------------------ | +| `MyBQDSN` | `MyBQDSN_Google` (Windows) | +| `MyBQDSN` | `MyBQDSN_google` (Linux/macOS) | + +**Use this when:** + +* You want side‑by‑side validation +* You need a rollback path +* Applications may still depend on the old DSN + +--- + +### 2. `replace` Mode (In‑place migration) + +**Behavior:** + +* DSN name remains **unchanged** +* Driver reference and configuration are updated **in place** +* Applications do not need configuration changes + +**Use this when:** + +* You are confident in the new driver +* DSN names must remain stable + +--- + +## When the Scripts Prompt for a DSN + +### Common Logic (All Platforms) + +The scripts first discover **all DSNs that use a Simba BigQuery driver**. + +There are three possible scenarios: + +--- + +### Scenario A: No Simba DSNs Found + +* Message is printed indicating no migration is needed +* Script exits safely without making changes + +--- + +### Scenario B: Exactly One Simba DSN Found + +* That DSN is **automatically selected** +* **No prompt** is shown +* Migration proceeds immediately + +--- + +### Scenario C: Multiple Simba DSNs Found + +* The script **lists all matching DSNs** +* The user is **prompted to select exactly one DSN** to migrate + +```text +Multiple Simba DSNs found: + [1] FinanceBQ + [2] AnalyticsBQ + +Enter the number of the DSN you want to migrate: +``` +* Migration continues only after a valid selection +* Only the selected DSN is migrated. + +This prevents accidental bulk or unintended migrations. + +--- + +## Platform‑Specific Details + +## Windows (PowerShell) + +### Script + +``` +migrate.ps1 +``` + +### Usage + +``` +migrate.ps1 -Mode copy -DriverInstaller GoogleBigQueryODBC.msi +migrate.ps1 -Mode replace -DriverInstaller GoogleBigQueryODBC.msi +``` + +### DSN Discovery + +* System DSNs: `HKLM\\SOFTWARE\\ODBC\\ODBC.INI` +* User DSNs: `HKCU\\SOFTWARE\\ODBC\\ODBC.INI` + +### Windows‑Specific Behavior + +* Installs the driver via **silent MSI** (`msiexec /quiet`) +* Copies DSN registry trees +* Updates `Driver` and `TrustedCerts` paths +* Decrypts `KeyFilePath_Enc` using **Windows DPAPI** +* Automatically tests the migrated DSN connection + +> ⚠️ Run from an **elevated PowerShell prompt** when migrating system DSNs. + +--- + +## Linux / macOS (Bash) + +### Script + +``` +migrate.sh +``` + +### Usage + +``` +./migrate.sh copy +./migrate.sh replace +``` + +### Installer Input + +The installer argument may be: + +* A directory +* `.zip` +* `.tar.gz` / `.tgz` + +The script automatically extracts and locates the driver library. + +### DSN Discovery + +* Uses `odbc.ini` +* Resolution order: + + 1. `$ODBCINI` environment variable (if set) + 2. `/etc/odbc.ini` + +### Linux/macOS‑Specific Behavior + +* Copies driver to: + + ``` + /usr/local/lib/google_odbc + ``` +* Creates a timestamped backup of `odbc.ini` +* Updates: + + * `[ODBC Data Sources]` + * Individual DSN sections +* Uses `sudo` automatically when required + +--- + +## Configuration Files Modified + +| Platform | Configuration | +| ----------- | --------------------------------- | +| Windows | Registry (ODBC.INI, ODBCINST.INI) | +| Linux/macOS | `odbc.ini` | + +All scripts create backups before modifying configuration. + +--- + +## Safety & Best Practices + +* **Start with `copy` mode** on all platforms +* Validate applications against the new DSN +* Keep backups until rollout is complete +* Use `replace` only when DSN names must remain unchanged + +--- + +## Summary Table + +| Feature | Windows | Linux/macOS | +| ------------------- | ------------------- | --------------------------- | +| Script | PowerShell | Bash | +| DSN store | Registry | odbc.ini | +| Installer | MSI | dir / zip / tar.gz | +| Copy mode | `_Google` | `_google` | +| Replace mode | In‑place | In‑place | +| Multi‑DSN prompt | Yes | Yes | +| Backup created | Implicit (registry) | Explicit `.bak.` | +| Credential handling | DPAPI decrypt | Plain‑text only | + +--- + +This unified behavior ensures a **predictable, safe migration experience across Windows, Linux, and macOS**. From be144be3fa685242851bdd199b99bc89fe17b970 Mon Sep 17 00:00:00 2001 From: Anshu6250 Date: Thu, 18 Dec 2025 10:09:11 +0000 Subject: [PATCH 6/6] checkers --- ci/migration/README.md | 154 ++++++++++++++++++++++------------------- 1 file changed, 83 insertions(+), 71 deletions(-) diff --git a/ci/migration/README.md b/ci/migration/README.md index 544afc5022..2765d1f2b1 100644 --- a/ci/migration/README.md +++ b/ci/migration/README.md @@ -1,25 +1,29 @@ # Cross‑Platform ODBC DSN Migration Scripts (Windows / Linux / macOS) -This repository provides **cross‑platform migration scripts** to move existing BigQuery ODBC DSNs from legacy **Simba drivers** to the new **ODBC Driver for BigQuery**. +This repository provides **cross‑platform migration scripts** to move existing +BigQuery ODBC DSNs from legacy **Simba drivers** to the new **ODBC Driver for +BigQuery**. The scripts support: -* **Windows** (PowerShell) -* **Linux** (Bash) -* **macOS** (Bash) +- **Windows** (PowerShell) +- **Linux** (Bash) +- **macOS** (Bash) -They follow the **same high‑level behavior and migration semantics** across all platforms, with platform‑specific implementation details. +They follow the **same high‑level behavior and migration semantics** across all +platforms, with platform‑specific implementation details. ---- +______________________________________________________________________ ## Goals of the Migration -* Seamlessly transition DSNs from Simba BigQuery drivers to the Google‑provided ODBC Driver for BigQuery -* Preserve existing DSN configuration wherever possible -* Support **safe testing (copy mode)** and **in‑place migration (replace mode)** -* Minimize manual registry / config file editing +- Seamlessly transition DSNs from Simba BigQuery drivers to the Google‑provided + ODBC Driver for BigQuery +- Preserve existing DSN configuration wherever possible +- Support **safe testing (copy mode)** and **in‑place migration (replace mode)** +- Minimize manual registry / config file editing ---- +______________________________________________________________________ ## What the Script Does @@ -28,12 +32,14 @@ At a high level, the script performs the following steps: 1. **Installs the new ODBC Driver for BigQuery** . 2. **Searches for existing DSNs** that use the legacy Simba BigQuery driver. 3. **Prompts the user to select a DSN** if multiple Simba-based DSNs are found. -4. **Migrates the selected DSN** based on the chosen migration mode (`copy` or `replace`). -5. **Updates registry entries for Windows** so the DSN points to the new Google BigQuery ODBC driver. +4. **Migrates the selected DSN** based on the chosen migration mode (`copy` or + `replace`). +5. **Updates registry entries for Windows** so the DSN points to the new Google + BigQuery ODBC driver. 6. **Decrypts and migrates encrypted credentials** (if present). 7. **Tests the migrated DSN connection** at the end. ---- +______________________________________________________________________ ## Supported Drivers @@ -42,7 +48,7 @@ At a high level, the script performs the following steps: | Windows | Simba ODBC Driver for Google BigQuery | ODBC Driver for BigQuery | | Linux / macOS | Simba Google BigQuery ODBC Connector | ODBC Driver for BigQuery | ---- +______________________________________________________________________ ## Migration Modes (All Platforms) @@ -52,9 +58,9 @@ Both scripts support the same two explicit modes. **Behavior:** -* Original Simba DSN is **left unchanged** -* A **new DSN is created** using the Google driver -* New DSN name is derived automatically +- Original Simba DSN is **left unchanged** +- A **new DSN is created** using the Google driver +- New DSN name is derived automatically | Original DSN | New DSN | | ------------ | ------------------------------ | @@ -63,26 +69,26 @@ Both scripts support the same two explicit modes. **Use this when:** -* You want side‑by‑side validation -* You need a rollback path -* Applications may still depend on the old DSN +- You want side‑by‑side validation +- You need a rollback path +- Applications may still depend on the old DSN ---- +______________________________________________________________________ ### 2. `replace` Mode (In‑place migration) **Behavior:** -* DSN name remains **unchanged** -* Driver reference and configuration are updated **in place** -* Applications do not need configuration changes +- DSN name remains **unchanged** +- Driver reference and configuration are updated **in place** +- Applications do not need configuration changes **Use this when:** -* You are confident in the new driver -* DSN names must remain stable +- You are confident in the new driver +- DSN names must remain stable ---- +______________________________________________________________________ ## When the Scripts Prompt for a DSN @@ -92,41 +98,42 @@ The scripts first discover **all DSNs that use a Simba BigQuery driver**. There are three possible scenarios: ---- +______________________________________________________________________ ### Scenario A: No Simba DSNs Found -* Message is printed indicating no migration is needed -* Script exits safely without making changes +- Message is printed indicating no migration is needed +- Script exits safely without making changes ---- +______________________________________________________________________ ### Scenario B: Exactly One Simba DSN Found -* That DSN is **automatically selected** -* **No prompt** is shown -* Migration proceeds immediately +- That DSN is **automatically selected** +- **No prompt** is shown +- Migration proceeds immediately ---- +______________________________________________________________________ ### Scenario C: Multiple Simba DSNs Found -* The script **lists all matching DSNs** -* The user is **prompted to select exactly one DSN** to migrate +- The script **lists all matching DSNs** +- The user is **prompted to select exactly one DSN** to migrate ```text Multiple Simba DSNs found: - [1] FinanceBQ - [2] AnalyticsBQ + [1] FinanceBQ + [2] AnalyticsBQ Enter the number of the DSN you want to migrate: ``` -* Migration continues only after a valid selection -* Only the selected DSN is migrated. + +- Migration continues only after a valid selection +- Only the selected DSN is migrated. This prevents accidental bulk or unintended migrations. ---- +______________________________________________________________________ ## Platform‑Specific Details @@ -147,20 +154,20 @@ migrate.ps1 -Mode replace -DriverInstaller GoogleBigQueryODBC.msi ### DSN Discovery -* System DSNs: `HKLM\\SOFTWARE\\ODBC\\ODBC.INI` -* User DSNs: `HKCU\\SOFTWARE\\ODBC\\ODBC.INI` +- System DSNs: `HKLM\\SOFTWARE\\ODBC\\ODBC.INI` +- User DSNs: `HKCU\\SOFTWARE\\ODBC\\ODBC.INI` ### Windows‑Specific Behavior -* Installs the driver via **silent MSI** (`msiexec /quiet`) -* Copies DSN registry trees -* Updates `Driver` and `TrustedCerts` paths -* Decrypts `KeyFilePath_Enc` using **Windows DPAPI** -* Automatically tests the migrated DSN connection +- Installs the driver via **silent MSI** (`msiexec /quiet`) +- Copies DSN registry trees +- Updates `Driver` and `TrustedCerts` paths +- Decrypts `KeyFilePath_Enc` using **Windows DPAPI** +- Automatically tests the migrated DSN connection > ⚠️ Run from an **elevated PowerShell prompt** when migrating system DSNs. ---- +______________________________________________________________________ ## Linux / macOS (Bash) @@ -181,35 +188,39 @@ migrate.sh The installer argument may be: -* A directory -* `.zip` -* `.tar.gz` / `.tgz` +- A directory +- `.zip` +- `.tar.gz` / `.tgz` The script automatically extracts and locates the driver library. ### DSN Discovery -* Uses `odbc.ini` -* Resolution order: +- Uses `odbc.ini` + +- Resolution order: 1. `$ODBCINI` environment variable (if set) 2. `/etc/odbc.ini` ### Linux/macOS‑Specific Behavior -* Copies driver to: +- Copies driver to: ``` /usr/local/lib/google_odbc ``` -* Creates a timestamped backup of `odbc.ini` -* Updates: - * `[ODBC Data Sources]` - * Individual DSN sections -* Uses `sudo` automatically when required +- Creates a timestamped backup of `odbc.ini` + +- Updates: + + - `[ODBC Data Sources]` + - Individual DSN sections + +- Uses `sudo` automatically when required ---- +______________________________________________________________________ ## Configuration Files Modified @@ -220,16 +231,16 @@ The script automatically extracts and locates the driver library. All scripts create backups before modifying configuration. ---- +______________________________________________________________________ ## Safety & Best Practices -* **Start with `copy` mode** on all platforms -* Validate applications against the new DSN -* Keep backups until rollout is complete -* Use `replace` only when DSN names must remain unchanged +- **Start with `copy` mode** on all platforms +- Validate applications against the new DSN +- Keep backups until rollout is complete +- Use `replace` only when DSN names must remain unchanged ---- +______________________________________________________________________ ## Summary Table @@ -244,6 +255,7 @@ All scripts create backups before modifying configuration. | Backup created | Implicit (registry) | Explicit `.bak.` | | Credential handling | DPAPI decrypt | Plain‑text only | ---- +______________________________________________________________________ -This unified behavior ensures a **predictable, safe migration experience across Windows, Linux, and macOS**. +This unified behavior ensures a **predictable, safe migration experience across +Windows, Linux, and macOS**.