SQL Connection String Format Error in Docker - sql-server

I am running a Docker container with a gMSA identity to connect to SQL Server via Windows Authentication. I confirmed the gMSA identity is working correctly within the container, however I'm receiving a SQL connection string format error:
"Format of the initialization string does not conform to specification starting at index 0."
My Dockerfile looks like this:
FROM microsoft/dotnet:2.2-runtime-nanoserver-sac2016
COPY . .
ENTRYPOINT ["dotnet", "Daemon.dll"]
CMD ["EventConfig:MqHostName=10.23.2.1", "ConnectionStrings:TestDb1=Data Source=10.23.2.1;Initial Catalog=Events;Integrated Security=true", "ConnectionStrings:TestDb2=Data Source=10.23.2.1;Initial Catalog=Notifications;Integrated Security=true", "ConnectionStrings:TestDb3=Data Source=10.23.2.1;Initial Catalog=TESTDB;Integrated Security=true"]
Running docker inspect on the container looks like the CMD parameters are parsed correctly, however I'm still receiving the error. The connection strings work without issue outside of Docker.
I've tried surrounding the connection strings by a backtick `, single quotes, double quotes, and slash . I've also tried passing in the strings as ENV variables instead of as CMD parameters. I've also tried adding a parser directive such as
# escape=`
to the top of my Dockerfile. Any help would be greatly appreciated.

For anyone who may have a similar issue, I determined how to escape the inner quotes using the \ character. The correctly formatted Dockerfile connection strings looks like this:
CMD ["EventConfig:MqHostName=10.23.2.1", "ConnectionStrings:TestDb1\"=Data Source=10.23.2.1;Initial Catalog=Events;Integrated Security=true\"", "ConnectionStrings:TestDb2=\"Data Source=10.23.2.1;Initial Catalog=Notifications;Integrated Security=true\"", "ConnectionStrings:TestDb3=\"Data Source=10.23.2.1;Initial Catalog=TESTDB;Integrated Security=true\""]

Related

SqlPackage seems to escape right square bracket ( ] ) in variable value passed to .dacpac

I'm passing a variable to my .dacpac but the text received is not what I passed. Example command:
sqlpackage /v:TextTest="abc]123" /Action:Publish /SourceFile:"my.dacpac" /TargetDatabaseName:MyDb /TargetServerName:"."
My variable $(TextTest) comes out as "abc]]123" instead of the original "abc]123".
Is there anything I can do to prevent SqlPackage from corrupting my input variables before they are passed to the .dacpac scripts?
Unfortunately, I don't think there is a good answer. This appears to be a very old bug. I'm seeing references to this issue going back 10 years.
Example A: https://web.archive.org/web/20220831180208/https://social.msdn.microsoft.com/forums/azure/en-US/f1d153c2-8f42-4148-b313-3449075c612f/sql-server-database-project-sqlcmd-variables-with-closing-square-brackets
They mention a "workaround" in the post, but they link to a Microsoft Connect issue which no longer exists and is not available on archive.org.
My best guess is that the "workaround" is to generate the deploy script rather than publishing, and then manually modify the variable value in the script...which is not really a workaround if you are working on a build/release pipeline or any sort of automation.
I tried testing this to see if it would make any difference using Microsoft.SqlServer.Dac.DacServices.Publish() directly (via dbatools PowerShell module), but unfortunately the problem exists there as well.
I also tested it against every keyboard accessible symbol and that is the only character it seems to have a problem with.
Another option, though still not great, is to generate the deployment script, then execute it using SQLCMD.EXE.
So for example this would work:
sqlpackage /Action:Script `
/DeployScriptPath:script.sql `
/SourceFile:foobar.dacpac `
/TargetConnectionString:'Server=localhost;Database=foobar;Uid=sa;Password=yourStrong(!)Password' `
/p:CommentOutSetVarDeclarations=True
SQLCMD -S 'localhost' -d 'foobar' -U 'sa' -P 'yourStrong(!)Password' `
-i .\script.sql `
-v TextTest = "abc]123" `
-v DatabaseName = "foobar"
/p:CommentOutSetVarDeclarations=True - This setting is key, otherwise SQLCMD will be overridden by what's in the file. Just make sure you specify ALL variables, and not just the one you need. So open the file to look at what is commented out and make sure you are supplying what is needed.
It's not a great option...but it's at least scriptable and doesn't require manual intervention.

psql Batch File - Escaping "Not Equal" Operator

I'm working on a batch file that will import data into the PostgreSQL database I use for testing. The batch file drops all of the databases, then recreates/reloads them from a previous dump file made from our production database. However, I sometimes run into a problem if I've accidentally left a connection open to that server/database. The "drop" portion fails because there are still users connected (me).
I've been trying to "tweak" my batch file with a command to disconnect all users from the database(s) prior to issuing the command to drop them, but I can't get that part (disconnection) to work. I've taken the disconnect code from another SO question How to drop a PostgreSQL database if there are active connections to it?, and I've been looking at other questions like How to execute postgres' sql queries from batch file? for help with the syntax.
I've also seen the "alternate" syntax for a not equal operator on the 9.2. Comparison Functions and Operators page of the official PostgreSQL documentation, but that seems to also be using "special" characters that would require escaping, so I'm not sure how to proceed.
At this point, the batch file looks like this:
#Echo OFF
SET PGPASSWORD=PASSWORD
cd /D "C:\PostgreSQL\bin"
psql.exe -h localhost -p 5432 -d postgres -U username -c 'SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = ''betadb'' AND pid \<\> pg_backend_pid();'
dropdb.exe -h localhost -p 5432 -U username betadb
psql.exe -h localhost -p 5432 -d postgres -U username < "C:\PostgresSQL\prodserverdump.sql"
Everything else works except for the pg_terminate_backend query. Every time I run that, I get strange errors indicating a problem with a path, or a file, or something else like that. I believe I've narrowed the problem down to the "not equal" operator (<>) in the query, but I can't seem to find the correct way to escape this so it doesn't try to pipe in data from a file that's not being defined.
I've tried using single backslashes (\) and double backslashes (\\), in front of one or both of the characters in the operator, but that doesn't appear to work. Is there a special way to escape the "greater than" and "less than" characters for the -c command line option in psql?
Using a combination of suggestions and "trial & error", I believe I found the correct syntax for executing this particular SQL command through a batch file.
Trying the "alternative" not equal operator (!=), I was still getting errors. They were different errors (it was giving me some nonsense about too many parameters), but it still wouldn't execute.
Using #Compo's suggestion from the comments, I then tried to enclose the entire SELECT statement in double quotes instead of single quotes. Still not quite there.
Finally, I removed the "extra" single quotes I was using around the database names from before. The query appears to have executed properly.
The final result looks like this:
#Echo OFF
SET PGPASSWORD=PASSWORD
cd /D "C:\PostgreSQL\bin"
psql.exe -h localhost -p 5432 -d postgres -U username -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = 'betadb' AND pid != pg_backend_pid();"
dropdb.exe -h localhost -p 5432 -U username betadb
psql.exe -h localhost -p 5432 -d postgres -U username < "C:\PostgresSQL\prodserverdump.sql"
I suppose I had assumed that, because all of the examples I had found were using single quotes to surround the SQL statement, that's what I had to use. Apparently, that assumption was incorrect.
Regardless, it all seems to be working correctly now. Hope this helps someone else who's looking to accomplish something similar.

Error in pgsql2shp postgresql

I want to dump a shapefile from my postgresql database with the following command line:
pgsql2shp -f output.shp -h localhost -u postgres -P admin parcel "SELECT * FROM parcel.export_output WHERE ParcelNoEng=116"
but it goes on showing the error:
ERROR: function postgis_version() does not exist
LINE 1: SELECT postgis_version()
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
What shall I do to get it work?
I have added Postgresql/version/bin to my environmental variable.
You're missing the PostGIS extension. Execute the following command in your PostgreSQL using a client of your choice, e.g. psql, and try again:
CREATE EXTENSION postgis;

Deploying SQL Changes Containing $(ESCAPE_SQUOTE())

I have a Database project in Visual Studio that I am attempting to deploy automatically to a test environment nightly. To accomplish this I am using TFS which leverages a PowerShell script to run "SqlPackage.exe" to deploy any changes that have occurred during the day.
Some of my procs contain logic that is run inside of a script that is part of a agent job step and contains the following code(In dynamic SQL):
$(ESCAPE_SQUOTE(JOBID))
When deploying changes that affect this proc, I get the following issue:
SQL Execution error: A fatal error occurred. Incorrect syntax was
encountered while $(ESCAPE_SQUOTE( was being parsed.
This is a known issue, it appears as though that is not supported. It appears to be a function of the "SQLCmd" command misinterpreting the $( characters as a variable:
"override the value of a SQL command (sqlcmd) variable used during a
publish action."
So how do I get around this? It seems to be a major limitation of "sqlcmd" that you can't disable variables, I don't see that parameter that supports that...
Update 1
Seems as through you can disable variable substitution from "sqlcmd" by feeding it the "-x" argument(Source, Documentation):
-x (disable variable substitution)
Still don't see a way to do this from "SqlPackage.exe" though.
It seems that sqlcmd looks for the $( as a token, so separating those two characters is good enough. You can do this with a dynamic query that does nothing more than break the query into two strings:
DECLARE #query nvarchar(256) = N'... $' + N'(ESCAPE_SQUOTE(JOBID)) ...';
EXEC sp_executesql #query
One way to get around this is to refactor the "$(ESCAPE_SQUOTE(JOBID))" string into a scalar function, then setup a PowerShell script to directly invoke the "Sqlcmd" command with the "-x" parameter to "Create/Alter" said function before running "SqlPackage.exe".
Looks something like this in PowerShell:
$sql = #"
USE $database
GO
CREATE FUNCTION [dbo].[GetJobID] ()
RETURNS NVARCHAR(MAX)
AS
BEGIN
RETURN '$(ESCAPE_SQUOTE(JOBID))'
END
GO
"#;
Sqlcmd -S $servername -U $username -P $password -Q $sql -x;
This is a pretty poor workaround, but it does accomplish the task. Really hoping for something better.
I propose another workaround
my job has a step running : DTEXEC.exe /SERVER "$(ESCAPE_NONE(SRVR))"
I just have to add a SQLCMD variable before:
:setvar SRVR "$(ESCAPE_NONE(SRVR))"
this way the toked is considered as SQLCMD variables $(SRVR) and is replaced by the requested value

PowerShell DTexec /ISServer pass a connectionstring as package variable

I want to execute a SSIS package on ISServer via PowerShell.
I used the script found on microsoft page. This doesn't work out for me.
I want to pass a connectionstring but not to assign to the connectionmanager but just as a variable string. In the connectionstring there are \ and ; present and powershell sees this as a new option. I just want it to be seen as a whole string.
I've tried everything, adding "\" and \"" like some websites suggested, used instead of \, put double quotes, put ' quotes, nothing works. Always getting the error optionMyServer\MyServer;Initial is not valid.
I can't removeMyServer\MyServer` because connection is to that instance.
The Connectionstring is assigned via a changing variable. So variable contains Data Source=MyServer\Myserver;Initial Catalog=SQL_MyArchive;Provider=SQLNCLI11;Integrated Security=SSPI;
dtexec /ISSERVER "\SSISDB\Test\Test.dtsx" /SERVER "MYServer" /ENVREFERENCE 8 /Par "$Package::ConnectionSource";`""Data Source=MyServer\Myserver;Initial Catalog=SQL_MyArchive;Provider=SQLNCLI11;Integrated Security=SSPI;"`"
How can i let the system see the whole connectionstring as a string? "" and "" does not work.
use the following syntax to pass a connectionstring to a variable (you missed a \")
/Par "$Package::ConnectionSource";\""Data Source=MyServer\Myserver;Initial Catalog=SQL_MyArchive;Provider=SQLNCLI11.1;Integrated Security=SSPI;"\"

Resources