From 1378a3000c6721cb87c8dd6bae5e87d9a251127d Mon Sep 17 00:00:00 2001 From: Justin Lettau Date: Sun, 13 Jan 2019 18:53:53 -0500 Subject: [PATCH] fix: user defined type scripting --- src/commands/pull.ts | 22 ++++++++++---- src/generators/mssql.ts | 63 ++++++++++++++++++++++++++++++++++++++- src/queries/interfaces.ts | 9 ++++-- src/queries/mssql.ts | 15 ++++++---- test/appveyor-cache.json | 6 ++++ 5 files changed, 102 insertions(+), 13 deletions(-) diff --git a/src/commands/pull.ts b/src/commands/pull.ts index 8229ffd..b50842b 100644 --- a/src/commands/pull.ts +++ b/src/commands/pull.ts @@ -173,12 +173,24 @@ export default class Pull { }); // types - types.forEach(item => { - const name = `${item.schema}.${item.name}.sql`; - const content = generator.type(item, columns); + types + .filter(item => !item.type) + .forEach(item => { + const name = `${item.schema}.${item.name}.sql`; + const content = generator.type(item); - file.write(config.output.types, name, content); - }); + file.write(config.output.types, name, content); + }); + + // table types + types + .filter(item => item.type && item.type.trim() === 'TT') + .forEach(item => { + const name = `${item.schema}.${item.name}.sql`; + const content = generator.tableType(item, columns); + + file.write(config.output.types, name, content); + }); // data data.forEach(item => { diff --git a/src/generators/mssql.ts b/src/generators/mssql.ts index 54493e5..78b64fb 100644 --- a/src/generators/mssql.ts +++ b/src/generators/mssql.ts @@ -268,9 +268,70 @@ export default class MSSQLGenerator { * Get type file content. * * @param item Row from query. + */ + type(item: SqlType) { + const objectId = `[${item.schema}].[${item.name}]`; + let output = ''; + + switch (this.config.idempotency.types) { + case 'if-exists-drop': + output += 'IF EXISTS ('; + output += EOL; + output += this.indent() + 'SELECT 1 FROM sys.types AS t'; + output += EOL; + output += this.indent() + 'JOIN sys.schemas s ON t.schema_id = s.schema_id'; + output += EOL; + output += this.indent() + `WHERE t.name = '${item.name}' AND s.name = '${item.schema}'`; + output += EOL; + output += ')'; + output += EOL; + output += `DROP TYPE ${item.name}`; + output += EOL; + output += 'GO'; + output += EOL; + break; + case 'if-not-exists': + output += `IF NOT EXISTS (`; + output += EOL; + output += this.indent() + 'SELECT 1 FROM sys.types AS t'; + output += EOL; + output += this.indent() + 'JOIN sys.schemas s ON t.schema_id = s.schema_id'; + output += EOL; + output += this.indent() + `WHERE t.name = '${item.name}' AND s.name = '${item.schema}'`; + output += EOL; + output += ')'; + output += EOL; + break; + } + + output += `CREATE TYPE ${objectId}`; + output += EOL; + output += `FROM ${item.system_type.toUpperCase()}`; + + switch (item.system_type) { + case 'char': + case 'nvarchar': + case 'varchar': + output += `(${item.max_length === -1 ? 'max' : item.max_length})`; + break; + case 'decimal': + case 'numeric': + output += `(${item.scale},${item.precision})`; + break; + } + + output += item.is_nullable ? ' NULL' : ' NOT NULL'; + + return output; + } + + /** + * Get table type file content. + * + * @param item Row from query. * @param columns Columns from query. */ - type(item: SqlType, columns: SqlColumn[]) { + tableType(item: SqlType, columns: SqlColumn[]) { const objectId = `[${item.schema}].[${item.name}]`; const type = item.type.trim(); let output = ''; diff --git a/src/queries/interfaces.ts b/src/queries/interfaces.ts index d1d5f50..4b3896e 100644 --- a/src/queries/interfaces.ts +++ b/src/queries/interfaces.ts @@ -36,8 +36,13 @@ export interface SqlTable extends AbstractSqlObject { /** * SQL type. */ -// tslint:disable-next-line:no-empty-interface -export interface SqlType extends AbstractSqlObject {} +export interface SqlType extends AbstractSqlObject { + system_type: string; + max_length: number; + precision: number; + scale: boolean; + is_nullable: boolean; +} /** * SQL column object. diff --git a/src/queries/mssql.ts b/src/queries/mssql.ts index 4c11c62..9c7f133 100644 --- a/src/queries/mssql.ts +++ b/src/queries/mssql.ts @@ -148,14 +148,19 @@ export const typesRead = ` o.object_id, o.type, s.name AS [schema], - t.name + t.name, + TYPE_NAME(t.system_type_id) as [system_type], + t.max_length, + t.precision, + t.scale, + t.is_nullable FROM - sys.table_types t - INNER JOIN sys.objects o ON o.object_id = t.type_table_object_id + sys.types t + LEFT JOIN sys.table_types tt ON tt.user_type_id = t.user_type_id + LEFT JOIN sys.objects o ON o.object_id = tt.type_table_object_id JOIN sys.schemas s ON t.schema_id = s.schema_id WHERE - o.type = 'TT' - AND t.is_user_defined = 1 + t.is_user_defined = 1 ORDER BY s.name, o.name diff --git a/test/appveyor-cache.json b/test/appveyor-cache.json index 9a0d480..b1172dc 100644 --- a/test/appveyor-cache.json +++ b/test/appveyor-cache.json @@ -128,6 +128,12 @@ "./_sql-database/tables/Sales.SpecialOffer.sql": "6a4dd953f1199f84324869d412ddc76b3783e85d", "./_sql-database/tables/Sales.SpecialOfferProduct.sql": "d64c059bc3e4d7f6f5843f7c973d6d36f06100f9", "./_sql-database/tables/Sales.Store.sql": "2df1f5fcafd6c96952bbebc30303810110c26d12", + "./_sql-database/types/dbo.AccountNumber.sql": "055ec65e54884c34ea6cb9e054cf550744e6ad97", + "./_sql-database/types/dbo.Flag.sql": "79e7e65d23ae0f9c89855c28e7fa12e4ea58575e", + "./_sql-database/types/dbo.NameStyle.sql": "f6c4f576d12ee8d600a657f5a803a58932b0d2d5", + "./_sql-database/types/dbo.Name.sql": "63b77aab82230cf5613ef06421329e9e0d53028e", + "./_sql-database/types/dbo.OrderNumber.sql": "b5b7741933db9658ad02816652109c4abdbaa4ca", + "./_sql-database/types/dbo.Phone.sql": "4a3b82ce5e309f44354a7694e453ca78dfae0427", "./_sql-database/data/Person.AddressType.sql": "7fe76948d9f9e7a3c1f2a14dbb2801b869637f22", "./_sql-database/data/Person.ContactType.sql": "587c5aaa9720bd5021d062dfaf6ee58c703223b5", "./_sql-database/data/Person.CountryRegion.sql": "995b413ea7a8eeb5e6ec47ceba45cf17d8186305",