/// <summary> /// Obtiene la cadena de comparación de campos /// </summary> private string GetSqlCompareFields(ConnectionTableModel table, ScriptsValidationOptions options) { string sql = string.Empty; // Añade la comparación de campos foreach (ConnectionTableFieldModel field in table.Fields) { string nullValue = GetDefaultNullValue(field.Type); string sourceField = $"IfNull({Provider.SqlHelper.FormatName("Target", field.Name)}, {nullValue})"; string targetField = $"IfNull({GetSqlReplaceField("Test", field, options)}, {nullValue})"; // Añade el operador si es necesario if (!string.IsNullOrWhiteSpace(sql)) { sql += "\t\t\t\tAND "; } // Si estamos comparando texto, en caso que queramos sólo comparar caracteres alfanuméricos o dígitos le añade el RegEx if (field.Type == ConnectionTableFieldModel.Fieldtype.String && options.CompareOnlyAlphaAndDigits) { sourceField = GetSqlRegexAlphaAndDigits(sourceField); targetField = GetSqlRegexAlphaAndDigits(targetField); } // Añade la comparación sql += $"{sourceField} = {targetField}" + Environment.NewLine; } // Devuelve la cadena SQL return(sql); }
/// <summary> /// Carga el esquema de la conexión /// </summary> internal async Task LoadSchemaAsync(ConnectionModel connection, CancellationToken cancellationToken) { SchemaDbModel schema = await GetDbProvider(connection).GetSchemaAsync(TimeSpan.FromMinutes(5), cancellationToken); // Limpia las tablas de la conexión connection.Tables.Clear(); // Agrega los campos foreach (TableDbModel tableSchema in schema.Tables) { ConnectionTableModel table = new ConnectionTableModel(connection); // Asigna las propiedades table.Name = tableSchema.Name; table.Description = tableSchema.Description; table.Schema = tableSchema.Schema; // Asigna los campos foreach (FieldDbModel fieldSchema in tableSchema.Fields) { ConnectionTableFieldModel field = new ConnectionTableFieldModel(table); // Asigna las propiedades field.Name = fieldSchema.Name; field.Description = fieldSchema.Description; field.Type = fieldSchema.DbType; // fieldSchema.Type.ToString(); field.Length = fieldSchema.Length; field.IsRequired = fieldSchema.IsRequired; field.IsKey = fieldSchema.IsKey; field.IsIdentity = fieldSchema.IsIdentity; // Añade el campo table.Fields.Add(field); } // Añade la tabla a la colección connection.Tables.Add(table); } }
/// <summary> /// Convierte una vista / tabla /// </summary> private ConnectionTableModel Convert(ConnectionModel connection, BaseTableDbModel baseTableView) { ConnectionTableModel view = new ConnectionTableModel(connection); // Asigna las propiedades view.Name = baseTableView.Name; view.Description = baseTableView.Description; view.Schema = baseTableView.Schema; // Asigna los campos foreach (FieldDbModel fieldSchema in baseTableView.Fields) { ConnectionTableFieldModel field = new ConnectionTableFieldModel(view); // Asigna las propiedades field.Name = fieldSchema.Name; field.Description = fieldSchema.Description; field.TypeText = fieldSchema.DbType; // fieldSchema.Type.ToString(); field.Type = Convert(fieldSchema.Type); field.Length = fieldSchema.Length; field.IsRequired = fieldSchema.IsRequired; field.IsKey = fieldSchema.IsKey; field.IsIdentity = fieldSchema.IsIdentity; // Añade el campo view.Fields.Add(field); } // Devuelve los datos return(view); }
/// <summary> /// Obtiene la cadena de validación sobre un archivo /// </summary> internal string GetSqlValidateFile(ConnectionTableModel table, bool countRecords, ScriptsValidationOptions options) { string sql = string.Empty; // Crea la cadena SQL de comparación si hay algún campo en la tabla if (table.Fields.Count > 0) { if (countRecords) { sql = "\tSELECT COUNT(*) AS Number"; } else { sql = "\t" + GetSqlHeaderCompare(table, "Test", "Target"); } sql += Environment.NewLine + $"\t\tFROM {GetFileNameTable(options.MountPathVariable, options.SubpathValidate, table.Name, options.FormatType, options.TablePrefixes)} AS Test"; sql += Environment.NewLine + "\t\tFULL OUTER JOIN {{" + options.DataBaseComputeVariable + "}}." + Provider.SqlHelper.FormatName(table.Name) + " AS Target"; sql += Environment.NewLine + "\t\t\tON " + GetSqlCompareFields(table, options).Trim(); sql += Environment.NewLine + $"\t\tWHERE {Provider.SqlHelper.FormatName("Target", table.Fields[0].Name)} IS NULL"; sql += Environment.NewLine + $"\t\t\tOR {Provider.SqlHelper.FormatName("Test", table.Fields[0].Name)} IS NULL"; sql += Environment.NewLine; } // Devuelve la cadena SQL return(sql); }
/// <summary> /// Obtiene la SQL de la consulta sobre el archivo de QlikView /// </summary> private string GetSqlQlikView(EtlFilesGenerator generator, ConnectionTableModel table) { string sql = "LOAD "; // Añade los campos de la tabla sql += GetQlikViewFields(table, "1 AS Flag_QV", true) + Environment.NewLine; // Añade el nombre de tabla sql += $" FROM [{Options.MountPathContent}/{generator.RemovePrefix(table.Name, Options.TablePrefixes)}.qvd] (qvd);" + Environment.NewLine; // Devuelve la cadena return(sql); }
/// <summary> /// Obtiene la cadena SQL de validación de tablas /// </summary> private string GetSqlValidation(EtlFilesGenerator generator, ConnectionTableModel table, bool prepareCountTables) { switch (Options.Mode) { case ScriptsValidationOptions.ValidationMode.Files: return(generator.GetSqlValidateFile(table, prepareCountTables, Options)); default: throw new Exception("Not implemented"); } }
/// <summary> /// Obtiene el nombre de la tabla de validación /// </summary> private string GetValidateTableName(ConnectionTableModel table, bool prepareCountTables) { if (prepareCountTables) { return($"{table.Name}_Validate_Count"); } else { return($"{table.Name}_Validate"); } }
public NodeTableViewModel(TreeSolutionBaseViewModel trvTree, NodeConnectionViewModel parent, ConnectionTableModel table, bool isTable) : base(trvTree, parent, table.FullName, TreeConnectionsViewModel.NodeType.Table.ToString(), TreeConnectionsViewModel.IconType.Table.ToString(), table, true, true, BauMvvm.ViewModels.Media.MvvmColor.Navy) { Table = table; IsTable = isTable; if (!IsTable) { Icon = TreeConnectionsViewModel.IconType.View.ToString(); } }
/// <summary> /// Obtiene la SQL de la consulta de la tabla en Spark /// </summary> private string GetSqlSelectSparkForQlikView(ConnectionTableModel table) { string sql = "LOAD "; // Añade los campos de la tabla sql += GetQlikViewFields(table, "Flag_Spark", true) + ";" + Environment.NewLine; // Añade la consulta de carga de base de datos sql += "SQL SELECT " + GetQlikViewFields(table, "1 AS Flag_Spark", false) + Environment.NewLine; // Añade el nombre de tabla sql += $" FROM Spark.{Options.DataBaseComputeVariable}.`{table.Name}`;" + Environment.NewLine; // Devuelve la cadena return(sql); }
/// <summary> /// Obtiene la cadena SQL de la cabecera con los campos a visualizar /// </summary> private string GetSqlHeaderCompare(ConnectionTableModel table, string sourceAlias, string targetAlias) { string sql = string.Empty; // Crea la cabecera con los nombres de campos foreach (ConnectionTableFieldModel field in table.Fields) { sql = sql.AddWithSeparator(Provider.SqlHelper.FormatName(sourceAlias, field.Name + "_" + sourceAlias), ","); sql = sql.AddWithSeparator(Provider.SqlHelper.FormatName(targetAlias, field.Name + "_" + targetAlias), ","); } // Devuelve la cadena creada return("SELECT " + sql); }
/// <summary> /// Obtiene la SQL para paginar una consulta en Spark /// </summary> private string GetSparkPaginatedSql(IDbProvider provider, ConnectionTableModel table, int actualPage, long blockSize) { string nameRowId = provider.SqlHelper.FormatName($"##_Row_Number_{table.Schema}_{table.Name}##"); string sqlFields = string.Empty; // Obtiene los nombres de campo foreach (ConnectionTableFieldModel field in table.Fields) { sqlFields = sqlFields.AddWithSeparator(provider.SqlHelper.FormatName(field.Name), ","); } // Devuelve la cadena SQL return(@$ "SELECT {sqlFields} FROM (SELECT Row_Number() OVER (ORDER BY 1 ASC) AS {nameRowId}, {sqlFields}
/// <summary> /// Obtiene una consulta sobre una tabla /// </summary> private string GetQuery(ConnectionTableModel table) { if (table == null) { return(string.Empty); } else { (string start, string end)separators = GetSqlSeparators(table.Connection); // Devuelve la consulta return($"SELECT {GetSqlSelectFields(separators, table)}{Environment.NewLine}\tFROM {GetSqlName(separators, table.Schema, table.Name)}{Environment.NewLine}"); } }
/// <summary> /// Obtiene la cadena de comparación de campos /// </summary> private string GetSqlCompareFields(ConnectionTableModel table) { string sql = string.Empty; // Añade la comparación de campos foreach (ConnectionTableFieldModel field in table.Fields) { // Añade el operador si es necesario if (!string.IsNullOrWhiteSpace(sql)) { sql += "\t\t\t\t\t\tAND "; } // Añade la comparación sql += $"IfNull(Target.`{field.Name}`, '') = IfNull(Test.`{field.Name}`, '')" + Environment.NewLine; } // Devuelve la cadena SQL return(sql); }
/// <summary> /// Obtiene la cadena SQL de comparación de tablas /// </summary> private string GetSqlCompare(ConnectionTableModel table, string pathVariable, string databaseVariable, string sufixTestTables) { string sql = string.Empty; // Crea la cadena SQL de comparación si hay algún campo en la tabla if (table.Fields.Count > 0) { sql += Environment.NewLine + "\t\t\tSELECT COUNT(*) AS Number"; sql += Environment.NewLine + "\t\t\t\tFROM parquet.`{{" + pathVariable + "}}" + $"/testing/{table.Name}{sufixTestTables}.parquet` AS Test"; sql += Environment.NewLine + "\t\t\t\tFULL OUTER JOIN {{" + databaseVariable + "}}.`" + table.Name + "` AS Target"; sql += Environment.NewLine + "\t\t\t\t\tON " + GetSqlCompareFields(table).Trim(); sql += Environment.NewLine + $"\t\t\t\tWHERE Target.`{table.Fields[0].Name}` IS NULL"; sql += Environment.NewLine + $"\t\t\t\t\tOR Test.`{table.Fields[0].Name}` IS NULL"; sql += Environment.NewLine; } // Devuelve la cadena SQL return(sql); }
/// <summary> /// Exporta una tabla particionando la consulta en varios <see cref="IDataReader"/> (porque por ejemplo spark carga todo el dataReader en memoria /// y da un error de OutOfMemory) /// </summary> private void ExportTable(BlockLogModel block, ConnectionModel connection, ConnectionTableModel table, string path, SolutionManager.FormatType formatType, long blockSize) { IDbProvider provider = Manager.DbScriptsManager.GetDbProvider(connection); long records = 0; int totalPages = 1; // Si es una conexión a Spark, se va a paginar si se supera el número de registros por blogue if (connection.Type == ConnectionModel.ConnectionType.Spark) { records = provider.GetRecordsCount($"SELECT * FROM {provider.SqlHelper.FormatName(table.Schema, table.Name)}", null, connection.TimeoutExecuteScript) ?? 0; totalPages = (int)Math.Ceiling((double)(records / blockSize)) + 1; } // Obtiene los datos for (int actualPage = 0; actualPage < totalPages; actualPage++) { string fileName; string sql; // Obtiene el nombre de archivo if (totalPages == 1) { fileName = GetFileName(path, table.Name, formatType); } else { fileName = GetFileName(path, table.Name, formatType, actualPage + 1); } // Graba el archivo de la página adecuada if (totalPages == 1) { sql = $"SELECT * FROM {provider.SqlHelper.FormatName(table.Schema, table.Name)}"; } else { sql = GetSparkPaginatedSql(provider, table, actualPage, blockSize); } //Log block.Info($"Reading page {actualPage + 1} / {records / blockSize + 1:#,##0} ({records:#,##0}) from table {table.Name}"); // Exporta la tabla ExportTable(block, provider, sql, fileName, formatType, connection.TimeoutExecuteScript); } }
/// <summary> /// Obtiene una cadena con los campos /// </summary> private string GetQlikViewFields(ConnectionTableModel table, string additionalField, bool addText) { string sql = string.Empty; // Añade los campos a la cadena foreach (ConnectionTableFieldModel field in table.Fields) { string fieldText = field.Name; // Añade la conversión a texto de QlikView if (addText && field.Type == ConnectionTableFieldModel.Fieldtype.Integer) { fieldText = $"TEXT({fieldText}) AS {fieldText}"; } // Añade el separador if (!string.IsNullOrWhiteSpace(sql)) { sql += ", " + Environment.NewLine + "\t"; } // Añade el campo sql += fieldText; } // Añade el campo adicional si es necesario if (!string.IsNullOrWhiteSpace(additionalField)) { // Añade el separador if (!string.IsNullOrWhiteSpace(sql)) { sql += ", "; } // Añade el campo adicional sql += additionalField; } // Devuelve la cadnea SQL return(sql); }
public NodeTableViewModel(BaseTreeViewModel trvTree, NodeConnectionViewModel parent, ConnectionTableModel table) : base(trvTree, parent, table.FullName, NodeType.Table, IconType.Table, table, true, true, BauMvvm.ViewModels.Media.MvvmColor.Navy) { Table = table; }
/// <summary> /// Abre una consulta /// </summary> private void OpenQuery(ConnectionTableModel table) { SolutionViewModel.MainController.OpenWindow(new Details.Queries.ExecuteQueryViewModel(SolutionViewModel, table?.Connection.Name, GetQuery(table))); }