Created
December 23, 2021 14:47
-
-
Save ahmad-moussawi/c9d3593cffe592f556078eca7dbf12bc to your computer and use it in GitHub Desktop.
A shell script that change the schema of the SQL Server DACPAC file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# This uitlity help to convert a dacpac from one schema to another | |
# taking into consideration some edge cases like when converting from/to dbo | |
# it assumes that you have 7-zip installed | |
in=${1:?Select dacpac file, usage: $0 <file>.dacpac <target_schema>} | |
schema=${2:?schema cannot be empty, usage: $0 <file>.dacpac <target_schema>} | |
# zip command | |
zip="/c/Program\\ Files/7-Zip/7z.exe" | |
if [[ ! -f $in ]]; then | |
echo ">> $in is not a readable file" | |
exit 1 | |
fi | |
unzip -o -d .tmp $in | |
# Detecting current schema | |
current_schemas=( $(grep '"SqlTable"' .tmp/model.xml | grep -oE '"\[[^]]+\]\.' | sort | uniq | sed 's/[][".]//g') ) | |
if [[ ${#current_schemas[@]} > 1 ]]; then | |
echo ">> multiple schemas found, select the source schema" | |
for i in "${!current_schemas[@]}"; do | |
echo "$i: ${current_schemas[i]}" | |
done | |
read -p '<< Your option: ' current | |
current="${current_schemas[current]}" | |
elif [[ ${#current_schemas[@]} -eq 1 ]]; then | |
current="${current_schemas[0]}" | |
else | |
current="dbo" | |
fi | |
if [[ $current == $schema ]]; then | |
echo ">> The current schema is already $schema, aborting." | |
rm -rf .tmp | |
exit 1 | |
fi | |
echo ">> Converting from $current -> $schema" | |
# pre manipulation add/remove some elements based on the target schema | |
if [[ $schema == 'dbo' ]]; then | |
# remove the SqlSchema Element since it's not needed when the target is dbo | |
sed -i "/<Element Type=\"SqlSchema\" Name=\"\[$current\]\"/,/<\/Element>/ d" .tmp/model.xml | |
# add the ExternalSource="BuiltIns" attribute for Schema references | |
sed -i "s:<References Name=\"\[$current\]\" />:<References ExternalSource=\"BuiltIns\" Name=\"[dbo]\" />:" .tmp/model.xml | |
else | |
# remove ExternalSource="BuiltIns" for Schema references | |
sed -i "s:<References ExternalSource=\"BuiltIns\" Name=\"\[dbo\]\" />:<References Name=\"[$schema]\" />:" .tmp/model.xml | |
# add the SqlSchema Element definition | |
sed -i "0,/<\/Element>/ s::</Element>\n<Element Type=\"SqlSchema\" Name=\"[$schema]\">\n\ | |
<Relationship Name=\"Authorizer\">\n\ | |
<Entry>\n\ | |
<References ExternalSource=\"BuiltIns\" Name=\"[DBOKEEP]\" />\n\ | |
</Entry>\n\ | |
</Relationship>\n\ | |
</Element>:" .tmp/model.xml | |
fi | |
files=('predeploy.sql' 'postdeploy.sql' 'model.xml') | |
for i in "${files[@]}"; do | |
file=".tmp/$i" | |
if [[ -f $file ]]; then | |
echo ">> replacing [$current] with [$schema] in $file" | |
sed -i "s/\[$current\]/[$schema]/gI" $file | |
# some cases where we have the schema without [] | |
# trying to match anyword followed directly by . | |
echo ">> replacing $current. with [$schema]. in $file" | |
sed -i "s/\<$current\./[$schema]./gI" $file | |
fi | |
done | |
sed -i 's/DBOKEEP/dbo/' .tmp/model.xml | |
# update checksum | |
checksum=$(sha256sum .tmp/model.xml | awk '{print $1}') | |
sed -i -e '/Checksum>/ d' -e "/<Checksums>/ a <Checksum Uri=\"/model.xml\">${checksum^^}</Checksum>" .tmp/Origin.xml | |
(cd .tmp; eval "$zip a -tzip ../${in%.dacpac}-$schema.dacpac *") | |
rm -rf .tmp | |
echo "Conversion done" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment