Git Product home page Git Product logo

rdagumampan / yuniql Goto Github PK

View Code? Open in Web Editor NEW
410.0 11.0 63.0 5.09 MB

Free and open source schema versioning and database migration made natively with .NET/6. NEW THIS MAY 2022! v1.3.15 released!

Home Page: https://yuniql.io

License: Apache License 2.0

C# 99.21% PowerShell 0.11% Batchfile 0.47% TSQL 0.22%
sql yuniql database-migrations sqlserver postgresql mariadb mysql redshift snowflake amazon-rds

yuniql's Introduction

yuniql yuniql-build-status AppVeyor tests (branch) Gitter Download latest build Download latest build

**** HELP DATA DEVELOPERS DISCOVER YUNIQL, PLEASE STAR THIS REPO. ITS FREE. :) THANKS! ****

yuniql (yuu-nee-kel). Free and open source schema versioning and database migration engine made natively with .NET Core. Use plain SQL scripts, bulk import CSV, integrate CI/CD pipelines, zero runtime dependencies and works with windows and linux. Supports SqlServer, PostgreSql, MySql, MariaDB, Snowflake, Redshift and Oracle*.

Working with CLI

Manage local db versions and run database migrations from your CLI tool. Perform local migration run or verify with uncommitted runs to test your scripts. Download latest release here. Install yuniql CLI with Chocolatey or use alternative ways listed here https://yuniql.io/docs/install-yuniql

dotnet tool install -g yuniql.cli
choco install yuniql
docker run --rm yuniql/cli:linux-x64-latest run --platform sqlserver --help
# powershell
Invoke-WebRequest -Uri https://github.com/rdagumampan/yuniql/releases/download/latest/yuniql-cli-win-x64-latest.zip -OutFile  "c:\temp\yuniql-win-x64-latest.zip"
Expand-Archive "c:\temp\yuniql-win-x64-latest.zip" -DestinationPath "c:\temp\yuniql-cli-latest"
cd c:\temp\yuniql-cli-latest
.\yuniql.exe run --platform sqlserver --help

Run migrations for SQL Server

docker run -d -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=P@ssw0rd!" -p 1400:1433 -d mcr.microsoft.com/mssql/server:2017-latest
SETX YUNIQL_CONNECTION_STRING "Server=localhost,1400;Database=yuniqldb;User Id=SA;Password=P@ssw0rd!;TrustServerCertificate=True"
SETX YUNIQL_WORKSPACE "c:\temp\yuniql-cli\samples\basic-sqlserver-sample"
git clone https://github.com/rdagumampan/yuniql.git c:\temp\yuniql-cli
cd c:\temp\yuniql-cli\samples\basic-sqlserver-sample

yuniql run -a --platform sqlserver
yuniql list --platform sqlserver

Running yuniql v1.0.1 for windows-x64
Copyright 2019 (C) Rodel E. Dagumampan. Apache License v2.0
Visit https://yuniql.io for documentation & more samples

+---------------+----------------------+------------+---------------+----------------------+--------------+
| SchemaVersion | AppliedOnUtc         | Status     | AppliedByUser | AppliedByTool        | Duration     |
+---------------+----------------------+------------+---------------+----------------------+--------------+
| v0.00         | 2021-02-04 06:06:46Z | Successful | sa            | yuniql-cli v1.1.55.0 | 164 ms / 0 s |
+---------------+----------------------+------------+---------------+----------------------+--------------+

Supported databases and platform tests

Amazon Aurora, Azure Synapse and Alibaba Aspara are being evaluated/developed/tested. For running migration from docker container, see instructions here.

Platforms Build Status Description Cloud Infrastructure Documentation
sqlserver yuniql-build-status Sql Server 2017 and later Azure, GCP, AWS Get started
postgresql yuniql-build-status PostgreSql v9.6 and later Azure, GCP, AWS Get started
mysql yuniql-build-status MySql v5.7 and later Azure, GCP, AWS Get started
mariadb yuniql-build-status MariaDb v10.2 and later Azure, GCP, AWS Get started
snowflake yuniql-build-status Last verified 12.2021 GCP Get started
redshift yuniql-build-status Last verified 12.2021 AWS Get started
oracle yuniql-build-status Preview build. Oracle 11g and later Oracle Cloud Get started
sap hana Analysis phase Expected Q1 2022 Azure
synapse Analysis phase Expected Q2 2022 Azure
aurora Ideation phase No release date yet AWS
asparadb Ideation phase No release date yet Alibaba

NOTE: Supported cloud platforms are based on limited testing and community feedbacks where users indicated the platform they were attempting to run against. yuniql primarily uses Amazon RDS as cloud provider for non-vendor specific platforms.

Distributions Build Status Description
Docker image linux-x64 yuniql-build-status docker pull yuniql/yuniql:linux-x64-latest
Docker imiage win-x64 yuniql-build-status docker pull yuniql/yuniql:win-x64-latest

Run migrations for PostgreSql, MySql and others

docker run -d -e POSTGRES_USER=sa -e POSTGRES_PASSWORD=P@ssw0rd! -e POSTGRES_DB=yuniqldb -p 5432:5432 postgres
SETX YUNIQL_CONNECTION_STRING "Host=localhost;Port=5432;Username=sa;Password=P@ssw0rd!;Database=yuniqldb"
SETX YUNIQL_WORKSPACE "c:\temp\yuniql-cli\samples\basic-postgresql-sample"
git clone https://github.com/rdagumampan/yuniql.git c:\temp\yuniql-cli
cd c:\temp\yuniql-cli\samples\basic-postgresql-sample

yuniql run -a --platform postgresql
yuniql list --platform postgresql

Working with Azure DevOps Pipelines Tasks

Run your database migration from Azure DevOps Pipelines. The tasks downloads package and cache it for later execution just like how Use .NET Core or Use Node tasks works. Find Yuniql on Azure DevOps MarketPlace. Developer guide is available here https://yuniql.io/docs/migrate-via-azure-devops-pipelines.

Working with Docker Container

Run your database migration thru a Docker container. This is specially helpful on Linux environments and CI/CD pipelines running on Linux Agents as it facilitates your migration without having to worry any local installations or runtime dependencies. Developer guide is available here https://yuniql.io/docs/migrate-via-docker-container.

git clone https://github.com/rdagumampan/yuniql.git c:\temp\yuniql-docker
cd c:\temp\yuniql-docker\samples\basic-sqlserver-sample

docker build -t sqlserver-example .
docker run sqlserver-example -c "<your-connection-string>" -a --platform sqlserver

Working with ASP.NET Core

Run your database migration when your ASP.NET Core host service starts up. This ensures that database is always at latest compatible state before operating the service. Applies to Worker and WebApp projects. Developer guide is available here https://yuniql.io/docs/migrate-via-aspnetcore-application.

dotnet add package Yuniql.AspNetCore
using Yuniql.AspNetCore;
...
...

//1. deploy new sql server on docker or use existing instance
//$ docker run -dit --name yuniql-sqlserver  -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=P@ssw0rd!" -p 1400:1433 -d mcr.microsoft.com/mssql/server:2017-latest

//2. create custom trace message sinks, this can be your own logger framework
var traceService = new ConsoleTraceService { IsDebugEnabled = true };

//3. run migrations
app.UseYuniql(traceService, new Yuniql.AspNetCore.Configuration
{
	Platform = SUPPORTED_DATABASES.SQLSERVER,
	Workspace = Path.Combine(Environment.CurrentDirectory, "_db"),
	ConnectionString = "Server=localhost,1400;Database=helloyuniql;User Id=SA;Password=P@ssw0rd!;TrustServerCertificate=True",
	IsAutoCreateDatabase = true, IsDebug = true
});

Working with .NET Core Console Application

Run your database migration when Console App starts. Developer guide is available here https://yuniql.io/docs/migrate-via-netcore-console-application.

dotnet add package Yuniql.Core
using Yuniql.Core;
...
...

static void Main(string[] args)
{
	//1. deploy new sql server on docker or use existing instance
	//$ docker run -dit -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=P@ssw0rd!" -p 1400:1433 -d mcr.microsoft.com/mssql/server:2017-latest

	//2. create custom trace message sinks, this can be your own logger framework
	var traceService = new ConsoleTraceService { IsDebugEnabled = true };

	//3. configure your migration run
	var configuration = Configuration.Instance;
	configuration.Platform = SUPPORTED_DATABASES.SQLSERVER;
	configuration.Workspace = Path.Combine(Environment.CurrentDirectory, "_db");
	configuration.ConnectionString = "Server=localhost,1400;Database=helloyuniql;User Id=SA;Password=P@ssw0rd!;TrustServerCertificate=True";
	configuration.IsAutoCreateDatabase = true;

	//4. run migrations
	var migrationServiceFactory = new MigrationServiceFactory(traceService);
	var migrationService = migrationServiceFactory.Create();
	migrationService.Run();

Advanced use cases

Contributing & asking for help

Please submit ideas for improvement or report a bug by creating an issue.
Alternatively, tag #yuniql on Twitter or drop me a message rdagumampanATgmail.com.

If this is your first time to participate in an open source initiative, you may look at issues labeled as first timer friendly issues. If you found an interesting case, you can fork this repository, clone to your dev machine, create a local branch, and make Pull Requests (PR) so I can review and merge your changes.

To prepare your dev machine, please visit https://github.com/rdagumampan/yuniql/wiki/Setup-development-environment

License

Copyright (C) 2019 Rodel E. Dagumampan

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 http://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.

Credits

Yuniql relies on many open-source projects and we would like to thanks:

Maintainers

yuniql's People

Contributors

black-eagle17 avatar bobi591 avatar bymse avatar davidhopkinsfbr avatar gasystarttask avatar jabestrada avatar jean-paul76 avatar mguoth avatar patrikmelanderving avatar rdagumampan avatar taurahsp avatar wahmedswl avatar wcontayon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

yuniql's Issues

Support command timeout

At current build all command timeouts were set to 0 which is infinity/unlimited. This is not good as the migration session may hang until some locked resources are released in the target server. A better approach is to accept --command-timeout when you call yuniql run

Example usage where timeout is 30 secs:

yuniql run -a --command-timeout 30s

Support parameterized tokens

Support parameter tokens so developers can use tokens inside their query and gets replace during migration run. This is particularly useful when developers uses databases and linked servers where names are suffixed by their environment.

For example, developer should be able to write something like this:
SELECT FirstName, LastName FROM [EMPLOYEEDB${Environment}].[dbo].[Employees]

And run migration like this:
yuniql run -c <connection-string> -e "Environment=DEV"
yuniql run -c <connection-string> -e "Environment=TEST"
yuniql run -c <connection-string> -e "Environment=PROD"

We should be able to capture multiple variables too
yuniql run -c <connection-string> -e "Environment=DEV" -e "LinkedServerName=SERVER01DEV"

Deploy https://getyuniql.org

For easier search engine indexing of documentation and discovery.

  • Purchase domain
  • Create hugo static site in GitHub, mirror in GitLab
  • Create GitLab pipeline
  • Publish GitLab pages
  • Setup custom domain
  • Setup LetsEncrypt SSL cert

External .sql files for creating and configuring target database

When we call yuniql run, it checks if the database exists and pre-created it when --autocreate-db true is passed. It also configures the metadata table where schema versions are tracked and stored. This scripts are embedded in the yuniql build. This makes it difficult to customize if users want a custom behavior when creating databases in DEV or TEST environments.

A solution is to make these scripts as part of init directory. Such that we will have 2 files there 01-create-database.sql and 02-configure-database.sql. Users can also organize it this way.

_init
   - __dev
      - 01-create-database.sql
      - 02-configure-database.sql
   - __tests
      - 01-create-database.sql
      - 02-configure-database.sql

Execute custom plugins in version folder

In some occasions the yuniql may not be able to support some tasks. For example, importing FileStream of images and uploading via network optimized transport mechanism are better left for developers to implement. In this feature, yuniql must be able to reflect on some binaries inside versioned folder and execute the action.

v1.00
  query.sql
  custom_action.dll

Failed to load plugin dependency using AssemblyLoadContext in .NET Core 3.0

I have a plugin with failing dependencies though I tried to follow as much MS recommendation on .NET Core 3.0. Been trying to figure out whats the problem for 2 days already :/. Appreciate an input or where to look. Thanks!

Details:

  • Entry point is a CLI app published by .NET Core 3.0 self-contained app

     //publishes as EXE file
     dotnet publish -c release -r win-x64 /p:publishsinglefile=true /p:publishtrimmed=true
  • Testing on Win-x64 and Linux-x64

  • .NET Core 3.0 assemblies

  • Plugin DLLs are published with this command

     //publishes as DLL files
     dotnet publish -c release -r linux-x64 /p:publishtrimmed=true -o ./app

The logs shows that file is there, it exists but the dependency resolver failed to load it and throws a FileNotFoundException. Strange.

C:\play\yuniql\yuniql-cli\bin\release\netcoreapp3.0\win-x64\publish>yuniql.exe run --plugins-path C:\temp\aztools\yuniql\0.0.0\x64\.plugins -p C:\play\yuniql\yuniql-plugins\postgresql\samples -c "Host=localhost;Port=5432;Username=xxx;Password=xxx;Database=yuniqldb" --platform postgresql -a 1 --debug
...
DBG   platformLowerCased: postgresql
DBG   pluginsPathParameter: C:\temp\aztools\yuniql\0.0.0\x64\.plugins
DBG   defaultAssemblyBasePath: C:\temp\aztools\yuniql\0.0.0\x64\.plugins\postgresql
...
DBG   Found plugin dir: C:\temp\aztools\yuniql\0.0.0\x64\.plugins\postgresql
DBG   Found plugin file: C:\temp\aztools\yuniql\0.0.0\x64\.plugins\postgresql\Npgsql.dll. ProductVersion: 4.1.1, FileVersion: 4.1.1.0
DBG   Found plugin file: C:\temp\aztools\yuniql\0.0.0\x64\.plugins\postgresql\Yuniql.Extensibility.dll. ProductVersion: 0.302.0, FileVersion: 0.302.0.0
DBG   Found plugin file: C:\temp\aztools\yuniql\0.0.0\x64\.plugins\postgresql\Yuniql.PostgreSql.deps.json. ProductVersion: , FileVersion:
DBG   Found plugin file: C:\temp\aztools\yuniql\0.0.0\x64\.plugins\postgresql\Yuniql.PostgreSql.dll. ProductVersion: 0.305.0, FileVersion: 0.305.0.0
DBG   Found plugin file: C:\temp\aztools\yuniql\0.0.0\x64\.plugins\postgresql\Yuniql.PostgreSql.pdb. ProductVersion: , FileVersion:

DBG   pluginAssemblyFilePath: C:\temp\aztools\yuniql\0.0.0\x64\.plugins\postgresql\Yuniql.PostgreSql.dll
DBG   loadedAssembly: Yuniql.PostgreSql, Version=0.305.0.0, Culture=neutral, PublicKeyToken=null
DBG   retryResolving: Npgsql, Version=4.1.1.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7
DBG   failedAssemblyFileExists: True
DBG   attempting to reload Npgsql, Version=4.1.1.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7 via streaming from C:\temp\aztools\yuniql\0.0.0\x64\.plugins\postgresql\Npgsql.dll

ERR   Failed to execute run function. Target database will be rolled back to its previous state.
System.IO.FileNotFoundException: Could not load file or assembly 'Npgsql, Version=4.1.1.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7'. The system cannot find the file specified.
File name: 'Npgsql, Version=4.1.1.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7'
   at Yuniql.PostgreSql.PostgreSqlDataService.GetConnectionInfo()
   at Yuniql.Core.MigrationService.Run(String workingPath, String targetVersion, Boolean autoCreateDatabase, List`1 tokenKeyPairs, Boolean verifyOnly, String delimeter)
   at Yuniql.CLI.CommandLineService.RunMigration(RunOption opts)

Unhandled exception. System.IO.FileNotFoundException: Could not load file or assembly 'Npgsql, Version=4.1.1.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7'. The system cannot find the file specified.
File name: 'Npgsql, Version=4.1.1.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7'
   at Yuniql.PostgreSql.PostgreSqlDataService.GetConnectionInfo()
   at Yuniql.Core.MigrationService.Run(String workingPath, String targetVersion, Boolean autoCreateDatabase, List`1 tokenKeyPairs, Boolean verifyOnly, String delimeter)
   at Yuniql.CLI.CommandLineService.RunMigration(RunOption opts)
   at Yuniql.Program.<>c__DisplayClass0_0.<Main>b__1(RunOption opts)
   at CommandLine.ParserResultExtensions.MapResult[T1,T2,T3,T4,T5,T6,T7,T8,TResult](ParserResult`1 result, Func`2 parsedFunc1, Func`2 parsedFunc2, Func`2 parsedFunc3, Func`2 parsedFunc4, Func`2 parsedFunc5, Func`2 parsedFunc6, Func`2 parsedFunc7, Func`2 parsedFunc8, Func`2 notParsedFunc)
   at Yuniql.Program.Main(String[] args)
C:\play\yuniql\yuniql-cli\bin\release\netcoreapp3.0\win-x64\publish>

PluginAssemblyLoadContext
https://github.com/rdagumampan/yuniql/blob/master/yuniql-core/PluginAssemblyLoadContext.cs

class PluginAssemblyLoadContext : AssemblyLoadContext
{
	private AssemblyDependencyResolver _resolver;

	public PluginAssemblyLoadContext(string pluginPath) : base(isCollectible: true)
	{
		_resolver = new AssemblyDependencyResolver(pluginPath);
	}
	protected override Assembly Load(AssemblyName name)
	{
		string assemblyPath = _resolver.ResolveAssemblyToPath(name);
		if (assemblyPath != null)
		{
			Console.WriteLine($"Loading assembly {assemblyPath} into the HostAssemblyLoadContext");
			return LoadFromAssemblyPath(assemblyPath);
		}

		return null;
	}
}

Load plugin from /app/.plugins/PostgreSql
https://github.com/rdagumampan/yuniql/blob/master/yuniql-core/MigrationServiceFactory.cs

// create the unloadable HostAssemblyLoadContext
var pluginAssemblyLoadContext = new PluginAssemblyLoadContext(pluginAssemblyBasePath);

//the plugin assembly into the HostAssemblyLoadContext. 
//the assemblyPath must be an absolute path.
var assembly = pluginAssemblyLoadContext.LoadFromAssemblyPath(pluginAssemblyFilePath);
pluginAssemblyLoadContext.Assemblies
	.ToList()
	.ForEach(a =>
	{
		_traceService.Debug($"loadedAssembly: {a.FullName}");
	});
pluginAssemblyLoadContext.Resolving += AssemblyContext_Resolving;
pluginAssemblyLoadContext.Unloading += AssemblyContext_Unloading;

var sqlDataService = assembly.GetTypes()
	.Where(t => t.Name.ToLower().Contains($"{platformLowerCased.ToLower()}dataservice"))
	.Select(t => Activator.CreateInstance(t, _traceService))
	.Cast<IDataService>()
	.First();

var bulkImportService = assembly.GetTypes()
	.Where(t => t.Name.ToLower().Contains($"{platformLowerCased.ToLower()}bulkimportservice"))
	.Select(t => Activator.CreateInstance(t, _traceService))
	.Cast<IBulkImportService>()
	.First();

var tokenReplacementService = new TokenReplacementService(_traceService);

var migrationService = new MigrationService(sqlDataService, bulkImportService, tokenReplacementService, directoryService, fileService, _traceService);
return migrationService;

Attempt to force resolve

private System.Reflection.Assembly AssemblyContext_Resolving(System.Runtime.Loader.AssemblyLoadContext assemblyContext, System.Reflection.AssemblyName failedAssembly)
{
	var pluginAssemblyLoadContext = assemblyContext as PluginAssemblyLoadContext;
	_traceService.Debug($"retryResolving: {failedAssembly.FullName}");

	var assemblyFilePath = Path.Combine(pluginAssemblyLoadContext.PluginPath, failedAssembly.Name + ".dll");
	_traceService.Debug($"failedAssemblyFileExists: {File.Exists(assemblyFilePath)}");

	using (var file = File.Open(assemblyFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
	{
		_traceService.Debug($"attempting to reload {failedAssembly.FullName} via streaming from {assemblyFilePath}");
		pluginAssemblyLoadContext.LoadFromStream(file);
	}

	//assemblyContext.LoadFromAssemblyPath(assemblyFilePath);
	//assemblyContext.LoadFromAssemblyName(new System.Reflection.AssemblyName(failedAssembly.Name));

	return null;
}

UPDATE 12/26/2019: I thought it was an issue only to linux but I was able to reproduce in Windows. Interestingly, when I run my platform tests which calls the Factory class directly but still the factory uses the AssemblyLoadContext, it works OK!.

The difference, it fails when called by CLI (a .NET Core 3.0 selfcontained EXE app) but OK when called from VSTestRunner (MSTEST).

SqlException (0x80131904): USE statement is not supported to switch between databases

Exception is thrown when tested in Azure Sql Database when running migration in Azure DevOps Pipelines.
Source: YUNIQL Azure DevOps Tasks
Az DevOps Task: v0.9.0
Yuniql version: latest

2019-12-19T23:21:39.4356069Z ##[section]Starting: run
2019-12-19T23:21:39.4478768Z ==============================================================================
2019-12-19T23:21:39.4478887Z Task         : Run YUNIQL CLI
2019-12-19T23:21:39.4478948Z Description  : Run YUNIQL CLI
2019-12-19T23:21:39.4479130Z Version      : 0.9.0
2019-12-19T23:21:39.4479188Z Author       : Rodel E. Dagumampan
2019-12-19T23:21:39.4479270Z Help         : This runs database migration with yuniql-cli
2019-12-19T23:21:39.4479340Z ==============================================================================
2019-12-19T23:21:39.7248593Z Run is executed
2019-12-19T23:21:39.7249018Z versionSpec: latest
2019-12-19T23:21:39.7284534Z Found tool in cache: yuniql 0.0.0 x64
2019-12-19T23:21:39.7321173Z [command]C:\hostedtoolcache\windows\yuniql\0.0.0\x64\yuniql.exe run -p d:\a\1\s\sqlserver-samples\visitph-db -c "Server=tcp:azsql-sandbox.database.windows.net,1433;Initial Catalog=azsql-sandbox;Persist Security Info=False;User ID=rdagumampan;Password=XXXXXXX;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" -a false --debug
2019-12-19T23:21:41.1624068Z INF   2019-12-19T23:21:41.1550456Z   Started migration from d:\a\1\s\sqlserver-samples\visitph-db.
2019-12-19T23:21:41.1644140Z INF   2019-12-19T23:21:41.1550456Z   Started migration from d:\a\1\s\sqlserver-samples\visitph-db.
2019-12-19T23:21:41.1939587Z INF   2019-12-19T23:21:41.1933217Z   No explicit target version requested. We'll use latest available locally v1.01 on d:\a\1\s\sqlserver-samples\visitph-db.
2019-12-19T23:21:41.1940163Z INF   2019-12-19T23:21:41.1933217Z   No explicit target version requested. We'll use latest available locally v1.01 on d:\a\1\s\sqlserver-samples\visitph-db.
2019-12-19T23:21:41.3546801Z DBG   2019-12-19T23:21:41.3542376Z   Executing sql statement: 
2019-12-19T23:21:41.3547188Z SELECT ISNULL(database_id,0) FROM [sys].[databases] WHERE name = 'azsql-sandbox'
2019-12-19T23:21:41.3548640Z DBG   2019-12-19T23:21:41.3542376Z   Executing sql statement: 
2019-12-19T23:21:41.3548948Z SELECT ISNULL(database_id,0) FROM [sys].[databases] WHERE name = 'azsql-sandbox'
2019-12-19T23:21:41.7413269Z DBG   2019-12-19T23:21:41.7408044Z   Executing sql statement: 
2019-12-19T23:21:41.7413795Z SELECT ISNULL(object_id,0) FROM [sys].[tables] WHERE name = '__YuniqlDbVersion'
2019-12-19T23:21:41.7414085Z DBG   2019-12-19T23:21:41.7408044Z   Executing sql statement: 
2019-12-19T23:21:41.7414287Z SELECT ISNULL(object_id,0) FROM [sys].[tables] WHERE name = '__YuniqlDbVersion'
2019-12-19T23:21:41.9484309Z INF   2019-12-19T23:21:41.9475347Z   Target database azsql-sandbox on tcp:azsql-sandbox.database.windows.net,1433 not yet configured for migration.
2019-12-19T23:21:41.9485578Z INF   2019-12-19T23:21:41.9475347Z   Target database azsql-sandbox on tcp:azsql-sandbox.database.windows.net,1433 not yet configured for migration.
2019-12-19T23:21:41.9490658Z DBG   2019-12-19T23:21:41.9486542Z   Executing sql statement: 
2019-12-19T23:21:41.9491041Z 
2019-12-19T23:21:41.9491209Z                     USE azsql-sandbox;
2019-12-19T23:21:41.9491338Z 
2019-12-19T23:21:41.9491469Z                     IF OBJECT_ID('[dbo].[__YuniqlDbVersion]') IS NULL 
2019-12-19T23:21:41.9491622Z                     BEGIN
2019-12-19T23:21:41.9491758Z 	                    CREATE TABLE [dbo].[__YuniqlDbVersion](
2019-12-19T23:21:41.9491915Z 		                    [Id] [SMALLINT] IDENTITY(1,1),
2019-12-19T23:21:41.9492055Z 		                    [Version] [NVARCHAR](32) NOT NULL,
2019-12-19T23:21:41.9492209Z 		                    [DateInsertedUtc] [DATETIME] NOT NULL,
2019-12-19T23:21:41.9492357Z 		                    [LastUpdatedUtc] [DATETIME] NOT NULL,
2019-12-19T23:21:41.9492517Z 		                    [LastUserId] [NVARCHAR](128) NOT NULL,
2019-12-19T23:21:41.9492654Z 		                    [Artifact] [VARBINARY](MAX) NULL,
2019-12-19T23:21:41.9492814Z 		                    CONSTRAINT [PK___YuniqlDbVersion] PRIMARY KEY CLUSTERED ([Id] ASC),
2019-12-19T23:21:41.9492981Z 		                    CONSTRAINT [IX___YuniqlDbVersion] UNIQUE NONCLUSTERED ([Version] ASC)
2019-12-19T23:21:41.9495413Z 	                    );
2019-12-19T23:21:41.9495754Z 
2019-12-19T23:21:41.9495963Z 	                    ALTER TABLE [dbo].[__YuniqlDbVersion] ADD  CONSTRAINT [DF___YuniqlDbVersion_DateInsertedUtc]  DEFAULT (GETUTCDATE()) FOR [DateInsertedUtc];
2019-12-19T23:21:41.9496196Z 	                    ALTER TABLE [dbo].[__YuniqlDbVersion] ADD  CONSTRAINT [DF___YuniqlDbVersion_LastUpdatedUtc]  DEFAULT (GETUTCDATE()) FOR [LastUpdatedUtc];
2019-12-19T23:21:41.9496405Z 	                    ALTER TABLE [dbo].[__YuniqlDbVersion] ADD  CONSTRAINT [DF___YuniqlDbVersion_LastUserId]  DEFAULT (SUSER_SNAME()) FOR [LastUserId];
2019-12-19T23:21:41.9496614Z                     END                
2019-12-19T23:21:41.9496766Z             
2019-12-19T23:21:41.9497241Z DBG   2019-12-19T23:21:41.9486542Z   Executing sql statement: 
2019-12-19T23:21:41.9497390Z 
2019-12-19T23:21:41.9497552Z                     USE azsql-sandbox;
2019-12-19T23:21:41.9497687Z 
2019-12-19T23:21:41.9497856Z                     IF OBJECT_ID('[dbo].[__YuniqlDbVersion]') IS NULL 
2019-12-19T23:21:41.9498009Z                     BEGIN
2019-12-19T23:21:41.9498182Z 	                    CREATE TABLE [dbo].[__YuniqlDbVersion](
2019-12-19T23:21:41.9498500Z 		                    [Id] [SMALLINT] IDENTITY(1,1),
2019-12-19T23:21:41.9499011Z 		                    [Version] [NVARCHAR](32) NOT NULL,
2019-12-19T23:21:41.9499158Z 		                    [DateInsertedUtc] [DATETIME] NOT NULL,
2019-12-19T23:21:41.9499692Z 		                    [LastUpdatedUtc] [DATETIME] NOT NULL,
2019-12-19T23:21:41.9499852Z 		                    [LastUserId] [NVARCHAR](128) NOT NULL,
2019-12-19T23:21:41.9500017Z 		                    [Artifact] [VARBINARY](MAX) NULL,
2019-12-19T23:21:41.9500210Z 		                    CONSTRAINT [PK___YuniqlDbVersion] PRIMARY KEY CLUSTERED ([Id] ASC),
2019-12-19T23:21:41.9500370Z 		                    CONSTRAINT [IX___YuniqlDbVersion] UNIQUE NONCLUSTERED ([Version] ASC)
2019-12-19T23:21:41.9500544Z 	                    );
2019-12-19T23:21:41.9500658Z 
2019-12-19T23:21:41.9500817Z 	                    ALTER TABLE [dbo].[__YuniqlDbVersion] ADD  CONSTRAINT [DF___YuniqlDbVersion_DateInsertedUtc]  DEFAULT (GETUTCDATE()) FOR [DateInsertedUtc];
2019-12-19T23:21:41.9501023Z 	                    ALTER TABLE [dbo].[__YuniqlDbVersion] ADD  CONSTRAINT [DF___YuniqlDbVersion_LastUpdatedUtc]  DEFAULT (GETUTCDATE()) FOR [LastUpdatedUtc];
2019-12-19T23:21:41.9501224Z 	                    ALTER TABLE [dbo].[__YuniqlDbVersion] ADD  CONSTRAINT [DF___YuniqlDbVersion_LastUserId]  DEFAULT (SUSER_SNAME()) FOR [LastUserId];
2019-12-19T23:21:41.9501526Z                     END                
2019-12-19T23:21:41.9501683Z             
2019-12-19T23:21:42.1398160Z ERR   2019-12-19T23:21:42.1392778Z   Failed to execute run function. Target database will be rolled back to its previous state. 
2019-12-19T23:21:42.1398712Z System.Data.SqlClient.SqlException (0x80131904): USE statement is not supported to switch between databases. Use a new connection to connect to a different database.
2019-12-19T23:21:42.1398966Z    at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
2019-12-19T23:21:42.1399151Z    at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
2019-12-19T23:21:42.1399346Z    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
2019-12-19T23:21:42.1399550Z    at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
2019-12-19T23:21:42.1399760Z    at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout, Boolean asyncWrite)
2019-12-19T23:21:42.1400687Z    at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite, String methodName)
2019-12-19T23:21:42.1400868Z    at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
2019-12-19T23:21:42.1401045Z    at Yuniql.SqlServer.SqlServerDataService.ConfigureDatabase()
2019-12-19T23:21:42.1401235Z    at Yuniql.Core.MigrationService.Run(String workingPath, String targetVersion, Boolean autoCreateDatabase, List`1 tokenKeyPairs, Boolean verifyOnly, String delimeter)
2019-12-19T23:21:42.1401415Z    at Yuniql.CLI.CommandLineService.RunMigration(RunOption opts)
2019-12-19T23:21:42.1401581Z ClientConnectionId:a7e250e4-af40-4dff-93e6-e37341183551
2019-12-19T23:21:42.1401718Z Error Number:40508,State:1,Class:16
2019-12-19T23:21:42.1401879Z ClientConnectionId before routing:c7f25386-76d3-4215-9f1b-5df9ed9b9964
2019-12-19T23:21:42.1402032Z Routing Destination:d48794e4030e.tr4419.westeurope1-a.worker.database.windows.net,11026
2019-12-19T23:21:42.1402305Z ERR   2019-12-19T23:21:42.1392778Z   Failed to execute run function. Target database will be rolled back to its previous state. 
2019-12-19T23:21:42.1413173Z System.Data.SqlClient.SqlException (0x80131904): USE statement is not supported to switch between databases. Use a new connection to connect to a different database.
2019-12-19T23:21:42.1413879Z    at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
2019-12-19T23:21:42.1414118Z    at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
2019-12-19T23:21:42.1414324Z    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
2019-12-19T23:21:42.1414542Z    at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
2019-12-19T23:21:42.1414757Z    at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout, Boolean asyncWrite)
2019-12-19T23:21:42.1415098Z    at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite, String methodName)
2019-12-19T23:21:42.1415277Z    at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
2019-12-19T23:21:42.1415418Z    at Yuniql.SqlServer.SqlServerDataService.ConfigureDatabase()
2019-12-19T23:21:42.1415811Z    at Yuniql.Core.MigrationService.Run(String workingPath, String targetVersion, Boolean autoCreateDatabase, List`1 tokenKeyPairs, Boolean verifyOnly, String delimeter)
2019-12-19T23:21:42.1415997Z    at Yuniql.CLI.CommandLineService.RunMigration(RunOption opts)
2019-12-19T23:21:42.1416138Z ClientConnectionId:a7e250e4-af40-4dff-93e6-e37341183551
2019-12-19T23:21:42.1416301Z Error Number:40508,State:1,Class:16
2019-12-19T23:21:42.1416442Z ClientConnectionId before routing:c7f25386-76d3-4215-9f1b-5df9ed9b9964
2019-12-19T23:21:42.1416610Z Routing Destination:d48794e4030e.tr4419.westeurope1-a.worker.database.windows.net,11026
2019-12-19T23:21:42.1435214Z Unhandled exception. System.Data.SqlClient.SqlException (0x80131904): USE statement is not supported to switch between databases. Use a new connection to connect to a different database.
2019-12-19T23:21:42.1435403Z Unhandled exception. System.Data.SqlClient.SqlException (0x80131904): USE statement is not supported to switch between databases. Use a new connection to connect to a different database.
2019-12-19T23:21:42.1435754Z    at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
2019-12-19T23:21:42.1435850Z    at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
2019-12-19T23:21:42.1436436Z    at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
2019-12-19T23:21:42.1436536Z    at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
2019-12-19T23:21:42.1436772Z    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
2019-12-19T23:21:42.1436873Z    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
2019-12-19T23:21:42.1437141Z    at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
2019-12-19T23:21:42.1437625Z    at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
2019-12-19T23:21:42.1438423Z    at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout, Boolean asyncWrite)
2019-12-19T23:21:42.1438558Z    at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout, Boolean asyncWrite)
2019-12-19T23:21:42.1438826Z    at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite, String methodName)
2019-12-19T23:21:42.1438978Z    at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite, String methodName)
2019-12-19T23:21:42.1439224Z    at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
2019-12-19T23:21:42.1439302Z    at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
2019-12-19T23:21:42.1439534Z    at Yuniql.SqlServer.SqlServerDataService.ConfigureDatabase()
2019-12-19T23:21:42.1439614Z    at Yuniql.SqlServer.SqlServerDataService.ConfigureDatabase()
2019-12-19T23:21:42.1439863Z    at Yuniql.Core.MigrationService.Run(String workingPath, String targetVersion, Boolean autoCreateDatabase, List`1 tokenKeyPairs, Boolean verifyOnly, String delimeter)
2019-12-19T23:21:42.1439987Z    at Yuniql.Core.MigrationService.Run(String workingPath, String targetVersion, Boolean autoCreateDatabase, List`1 tokenKeyPairs, Boolean verifyOnly, String delimeter)
2019-12-19T23:21:42.1440365Z    at Yuniql.CLI.CommandLineService.RunMigration(RunOption opts)
2019-12-19T23:21:42.1440447Z    at Yuniql.CLI.CommandLineService.RunMigration(RunOption opts)
2019-12-19T23:21:42.1440677Z    at Yuniql.Program.<>c__DisplayClass0_0.<Main>b__1(RunOption opts)
2019-12-19T23:21:42.1446406Z    at Yuniql.Program.<>c__DisplayClass0_0.<Main>b__1(RunOption opts)
2019-12-19T23:21:42.1449051Z    at CommandLine.ParserResultExtensions.MapResult[T1,T2,T3,T4,T5,T6,T7,T8,TResult](ParserResult`1 result, Func`2 parsedFunc1, Func`2 parsedFunc2, Func`2 parsedFunc3, Func`2 parsedFunc4, Func`2 parsedFunc5, Func`2 parsedFunc6, Func`2 parsedFunc7, Func`2 parsedFunc8, Func`2 notParsedFunc)
2019-12-19T23:21:42.1449279Z    at CommandLine.ParserResultExtensions.MapResult[T1,T2,T3,T4,T5,T6,T7,T8,TResult](ParserResult`1 result, Func`2 parsedFunc1, Func`2 parsedFunc2, Func`2 parsedFunc3, Func`2 parsedFunc4, Func`2 parsedFunc5, Func`2 parsedFunc6, Func`2 parsedFunc7, Func`2 parsedFunc8, Func`2 notParsedFunc)
2019-12-19T23:21:42.1454552Z    at Yuniql.Program.Main(String[] args)
2019-12-19T23:21:42.1454645Z    at Yuniql.Program.Main(String[] args)
2019-12-19T23:21:42.1456833Z ClientConnectionId:a7e250e4-af40-4dff-93e6-e37341183551
2019-12-19T23:21:42.1456929Z ClientConnectionId:a7e250e4-af40-4dff-93e6-e37341183551
2019-12-19T23:21:42.1547390Z Error Number:40508,State:1,Class:16
2019-12-19T23:21:42.1548505Z Error Number:40508,State:1,Class:16
2019-12-19T23:21:42.1648176Z ClientConnectionId before routing:c7f25386-76d3-4215-9f1b-5df9ed9b9964
2019-12-19T23:21:42.1648318Z ClientConnectionId before routing:c7f25386-76d3-4215-9f1b-5df9ed9b9964
2019-12-19T23:21:42.1653601Z Routing Destination:d48794e4030e.tr4419.westeurope1-a.worker.database.windows.net,11026
2019-12-19T23:21:42.1653723Z Routing Destination:d48794e4030e.tr4419.westeurope1-a.worker.database.windows.net,11026
2019-12-19T23:21:42.1655152Z 
2019-12-19T23:21:42.1715407Z ##[error]The process 'C:\hostedtoolcache\windows\yuniql\0.0.0\x64\yuniql.exe' failed with exit code 3762504530
2019-12-19T23:21:42.1738740Z ##[section]Finishing: run

yuniql erase

When running integration tests in a non-containerized environment, we usually have a single database running on some sql server instance and we constantly clean every test execution. If we have yuniql erase which can only be executed in TEST environment, we can accelerate this process.

This feature however could have potential high risks of human mistakes that developers misconfigure the PRODUCTION release pipelines and accidentally erasing the PRODUCTION database.

Support PostgreSQL

To fully verify the extensibility capability of yuniql, we'd like to support another RDMS platform. PostgreSQL is natural choice, its open source, its wide used by developers. An ideal approach to run this would be like this

yuniql init
yuniql run --platform pgsql

Install yuniql via chocolatey

Install yuniql via cholatey

choco install yuniql
choco upgrade yuniql 

choco install yuniql --version=1.1.0
choco upgrade yuniql --version=1.1.0

Unable to connect to server when there is no access to Master DB

Stacktrace

c:\Temp\yuniql-nightly>yuniqlx baseline -c "Server=XXXXXX;Initial Catalog=XXXXX;Persist Security Info=False;User ID=XXXXX;Password=XXXXX;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" -p "C:\Temp\yuniql-nightly\v0.00" ERR 2019-11-01T14:26:59.6347662Z Failed to execute init function. Microsoft.SqlServer.Management.Common.ConnectionFailureException: Failed to connect to server obs-sqlserver-dev.database.windows.net,1433. ---> System.Data.SqlClient.SqlException (0x80131904): The server principal "obsdbraw_adm" is not able to access the database "master" under the current security context. Cannot open user default database. Login failed. Login failed for user 'obsdbraw_adm'. at System.Data.ProviderBase.DbConnectionPool.CheckPoolBlockingPeriod(Exception e) at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 retry, DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 retry, DbConnectionOptions userOptions) at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource1 retry)
at System.Data.SqlClient.SqlConnection.Open()
at Microsoft.SqlServer.Management.Common.ConnectionManager.InternalConnect()
at Microsoft.SqlServer.Management.Common.ConnectionManager.Connect()
ClientConnectionId:c4c09285-30df-4cc9-80a6-b6660e86a1e4
Error Number:916,State:2,Class:14
--- End of inner exception stack trace ---
at Microsoft.SqlServer.Management.Common.ConnectionManager.Connect()
at ArdiLabs.Yuniql.Extensions.BaselineService.Init(String connectionString)
at ArdiLabs.Yuniql.Extensions.BaselineService.Run(String sourceConnectionString, String destinationFullPath)
at ArdiLabs.Yuniql.Extensions.Program.RunBaselineOption(BaselineOption opts)
Unhandled exception. Microsoft.SqlServer.Management.Common.ConnectionFailureException: Failed to connect to server obs-sqlserver-dev.database.windows.net,1433.
---> System.Data.SqlClient.SqlException (0x80131904): The server principal "obsdbraw_adm" is not able to access the database "master" under the current security context.`

Lost encoding during bulk import of CSV

Imported CSV files loses the right encoding for charatcters like Ø.

  1. Create setup.sql on v0.00
IF NOT EXISTS(SELECT * FROM sys.tables WHERE name = 'Asset') 
BEGIN
CREATE TABLE [dbo].[Asset](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[AssetId] [varchar](50) NOT NULL,
	[Name] [nvarchar](255) NOT NULL,
	[Description] [varchar](max) NULL,
	[Capacity] [int] NULL,
	[DateInsertedUtc] [datetime] NULL,
	[LastUpdatedUtc] [datetime] NULL,
	[LastUserId] [varchar](255) NULL,
PRIMARY KEY CLUSTERED 
(
	[Id] ASC
))
END
GO
  1. Create Asset.csv as v0.00
Id|AssetId|Name|Description|Capacity|DateInsertedUtc|LastUpdatedUtc|LastUserId
1|A1|Vindmølle|||||
1|A2|Havmøllepark|||||
  1. Run migration
yuniql run -a -c "Server=.\;Database=ASSETD;Trusted_Connection=True;" --delimeter "|"
  1. Check results if encoding is OK
SELECT * FROM Asset;

Make nuget package for netcore apps

Make nuget package for netcore

use Yuniql;
...
app.UseYuniqlMigrations(startAutomatic:true,autoCreateDatabase:true);
...
var yuniqlService = new Yunil.MigrationService();
yuniqlService.Run(autoCreateDatabase:true);

Environment aware scripts

Some scripts may only be applicable in specific environment. For example,you may want to create big tables with partition functions and partition schemes in PROD but not in DEV and TEST environment. You may name the file with ENV.create_big_tables.sql

yuniql run -a --environment DEV
yuniql run -a --environment TEST
yuniql run -a --environment STAGING
yuniql run -a --environment PROD

Create a example migration project in repo

The idea is to create a /yuniql/example in the repo to demonstrate a ready-for-use migration structure and run yuniql right away. This would ease learning curve on how the tool works.

yuniql run -u | --uncommitted

yuniql run -u | --uncommitted

The idea for this is to perform an uncommitted run of the migration to verify if all works well. At present, when we run migration we have to physically create databases and commit all changes. It would be good to have soft run and check if the target database can actually fully support the migration run before committing in PROD.

Failed migration using Docker task in Azure DevOps

2019-12-21T20:14:22.2350020Z ##[section]Starting: run
2019-12-21T20:14:22.2355086Z ==============================================================================
2019-12-21T20:14:22.2355209Z Task         : Docker
2019-12-21T20:14:22.2355289Z Description  : Build or push Docker images, login or logout, or run a Docker command
2019-12-21T20:14:22.2355405Z Version      : 2.162.0
2019-12-21T20:14:22.2355471Z Author       : Microsoft Corporation
2019-12-21T20:14:22.2355569Z Help         : https://docs.microsoft.com/azure/devops/pipelines/tasks/build/docker
2019-12-21T20:14:22.2355658Z ==============================================================================
2019-12-21T20:14:23.2077824Z [command]/usr/bin/docker run visitph-example -c "XXXXXXXXX"
2019-12-21T20:14:24.0640047Z INF   2019-12-21T20:14:24.0603392Z   Started migration from db.
...
...
...
2019-12-21T20:14:25.8293130Z INF   2019-12-21T20:14:25.8286452Z   Found the 0 script files on db/v1.01
2019-12-21T20:14:25.8293421Z INF   2019-12-21T20:14:25.8287095Z   
2019-12-21T20:14:25.8293770Z INF   2019-12-21T20:14:25.8288013Z   Found the 0 bulk files on db/v1.01
2019-12-21T20:14:25.8294031Z INF   2019-12-21T20:14:25.8288797Z   
2019-12-21T20:14:25.8462526Z INF   2019-12-21T20:14:25.8456913Z   Completed migration to version db/v1.01
2019-12-21T20:14:25.8462920Z INF   2019-12-21T20:14:25.8458386Z   Found the 2 script files on db/_draft
2019-12-21T20:14:25.8463306Z INF   2019-12-21T20:14:25.8459311Z   02-initialize-destination-tables.sql\r\n\t01-setup-destination-tables.sql
2019-12-21T20:14:25.9001926Z ERR   2019-12-21T20:14:25.8976927Z   Failed to execute run function. Target database will be rolled back to its previous state. 
2019-12-21T20:14:25.9002708Z System.Data.SqlClient.SqlException (0x80131904): Invalid object name 'dbo.Destination'.
2019-12-21T20:14:25.9003236Z    at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
2019-12-21T20:14:25.9003585Z    at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
2019-12-21T20:14:25.9003763Z    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
2019-12-21T20:14:25.9004075Z    at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
2019-12-21T20:14:25.9004258Z    at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout, Boolean asyncWrite)
2019-12-21T20:14:25.9004401Z    at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite, String methodName)
2019-12-21T20:14:25.9005196Z    at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
2019-12-21T20:14:25.9005335Z    at Yuniql.SqlServer.SqlServerDataService.ExecuteNonQuery(IDbConnection activeConnection, String sqlStatement, IDbTransaction transaction)
2019-12-21T20:14:25.9005457Z    at Yuniql.Core.MigrationService.<>c__DisplayClass12_1.<RunNonVersionScripts>b__3(String sqlStatement)
2019-12-21T20:14:25.9005817Z    at System.Collections.Generic.List`1.ForEach(Action`1 action)
2019-12-21T20:14:25.9005964Z    at Yuniql.Core.MigrationService.<>c__DisplayClass12_0.<RunNonVersionScripts>b__1(String scriptFile)
2019-12-21T20:14:25.9006071Z    at System.Collections.Generic.List`1.ForEach(Action`1 action)
2019-12-21T20:14:25.9006225Z    at Yuniql.Core.MigrationService.RunNonVersionScripts(IDbConnection connection, IDbTransaction transaction, String directoryFullPath, List`1 tokens)
2019-12-21T20:14:25.9006366Z    at Yuniql.Core.MigrationService.Run(String workingPath, String targetVersion, Boolean autoCreateDatabase, List`1 tokenKeyPairs, Boolean verifyOnly, String delimeter)
2019-12-21T20:14:25.9006519Z    at Yuniql.CLI.CommandLineService.RunMigration(RunOption opts)

Create README file for each non-version folder during init

When user calls yuniql init as baseline directory structure is created. If user did not add any files and push the workspace into git, the empty folders will not be committed and structure is broken the repo is cloned and executed in another machine.

Fail migrations when some tokens are not replaced

Fail migrations when some tokens are not replaced? If user failed to pass the required tokens, the scripts will be successfully executed and objects could be created but may fail during actual by client or application.

CREATE VIEW [dbo].[VwVisitor]
AS
SELECT TOP (1000) [VisitorID]
      ,[FirstName] AS '${VwColumnPrefix}FirstName'
      ,[FirstName] AS '${VwColumnPrefix}LastName'
      ,[Address] AS '${VwColumnPrefix}Address'
      ,[Email] AS '${VwColumnPrefix}Email'
FROM [dbo].[Visitor]

Azure SQL Database already exists but yuniql attempts to re-create

SELECT ISNULL(DB_ID (N'testsql'),0);
INF   2019-11-03T12:16:51.9723644Z   Target database does not exist. Creating database testsql on tcp:testsqlrddag.database.windows.net,1433.
DBG   2019-11-03T12:16:51.9741370Z   Executing sql statement:
CREATE DATABASE testsql;
ERR   2019-11-03T12:16:52.7862509Z   Failed to execute run function. Target database will be rolled back to its previous state.
System.Data.SqlClient.SqlException (0x80131904): CREATE DATABASE permission denied in database 'master'.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite, String methodName)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at ArdiLabs.Yuniql.DbHelper.ExecuteNonQuery(String connectionString, String sqlStatement) in C:\play\yuniql\src\DbHelper.cs:line 21
   at ArdiLabs.Yuniql.MigrationService.CreateDatabase(String targetDatabaseName) in C:\play\yuniql\src\MigrationService.cs:line 149
   at ArdiLabs.Yuniql.MigrationService.Run(String workingPath, String targetVersion, Boolean autoCreateDatabase, List`1 tokens, Boolean verificationRunOnly) in C:\play\yuniql\src\MigrationService.cs:line 36
   at ArdiLabs.Yuniql.Program.RunMigration(RunOption opts) in C:\play\yuniql\src\Program.cs:line 161
ClientConnectionId:96a2a90c-fd37-4a5a-bb2a-49953600f231
Error Number:262,State:1,Class:14

yuniql rebase

yuniql rebase

This would clear all the folders of the migration and would somehow create a new baseline base on the content of all the scripts (and/or base on the states of the current database).

Support schema for bulk import CSV files

Yuniql support bulk import of master data and lookup tables thru a CSV file with the same name as the destination table. While this works for majority of the cases, it assumes the target database and tables uses dbo schema. It may not work if the target table such as Visitor.csv targets registration.Visitor and the dbo.Visitor does not exists.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.