/// <summary> /// Load the specified stream /// </summary> public static SqlFeature Load(Stream source) { var retVal = new SqlFeature(); // Get deployment sql using (var sr = new StreamReader(source)) retVal.m_deploySql = sr.ReadToEnd(); var xmlSql = m_metaRegx.Match(retVal.m_deploySql.Replace("\r", "").Replace("\n", "")); if (xmlSql.Success) { var xmlText = xmlSql.Groups[1].Value.Replace("*", ""); XmlDocument xd = new XmlDocument(); xd.LoadXml(xmlText); retVal.Id = xd.SelectSingleNode("/feature/@id")?.Value ?? "0-0"; retVal.Name = xd.SelectSingleNode("/feature/@name")?.Value ?? "Other"; retVal.Description = xd.SelectSingleNode("/feature/summary/text()")?.Value ?? "other update"; retVal.Remarks = xd.SelectSingleNode("/feature/remarks/text()")?.Value ?? "other update"; retVal.Url = new Uri(xd.SelectSingleNode("/feature/url/text()")?.Value ?? $"http://help.santesuite.org/ops/santedb/fixpatch/{retVal.Id}"); retVal.m_checkRange = xd.SelectSingleNode("/feature/@applyRange")?.Value; retVal.Scope = xd.SelectSingleNode("/feature/@scope")?.Value; retVal.m_checkSql = xd.SelectSingleNode("/feature/isInstalled/text()")?.Value; retVal.m_canInstallSql = xd.SelectSingleNode("/feature/canInstall/text()")?.Value; retVal.MustSucceed = Boolean.Parse(xd.SelectSingleNode("/feature/isInstalled/@mustSucceed")?.Value ?? "false"); retVal.InvariantName = xd.SelectSingleNode("/feature/@invariantName")?.Value; } else { throw new InvalidOperationException("Invalid SQL update file"); } return(retVal); }
/// <summary> /// Returns true if the migration has been installed /// </summary> public static bool IsInstalled(this DataContext conn, SqlFeature migration) { conn.Open(); string checkSql = migration.GetCheckSql(), preConditionSql = migration.GetPreCheckSql(); if (!String.IsNullOrEmpty(preConditionSql)) { using (var cmd = conn.Connection.CreateCommand()) { cmd.CommandText = preConditionSql; cmd.CommandType = System.Data.CommandType.Text; if ((bool?)cmd.ExecuteScalar() != true) // can't install { throw new ConstraintException($"Pre-check for {migration.Id} failed"); } } } if (!String.IsNullOrEmpty(checkSql)) { using (var cmd = conn.Connection.CreateCommand()) { cmd.CommandText = checkSql; cmd.CommandType = System.Data.CommandType.Text; return((bool?)cmd.ExecuteScalar() == true); } } return(true); }
/// <summary> /// Install the specified object /// </summary> public static bool Install(this DataContext conn, SqlFeature migration) { conn.Open(); var stmts = migration.GetDeploySql().Split(new string[] { "--#!" }, StringSplitOptions.RemoveEmptyEntries); foreach (var dsql in stmts) { using (var cmd = conn.Connection.CreateCommand()) { try { if (String.IsNullOrEmpty(dsql.Trim())) { continue; } cmd.CommandTimeout = 36000; cmd.CommandText = dsql; cmd.CommandType = CommandType.Text; m_traceSource.TraceVerbose("EXEC: {0}", dsql); cmd.ExecuteScalar(); } catch (Exception e) { if (!cmd.CommandText.Contains("OPTIONAL")) { #if DEBUG m_traceSource.TraceError("SQL Statement Failed: {0} - {1}", cmd.CommandText, e.Message); #endif throw; } else { m_traceSource.TraceWarning("Optional SQL Statement Failed: {0}", cmd.CommandText); } } } } return(true); }
/// <summary> /// Load the available features /// </summary> public static IEnumerable <IDataFeature> GetFeatures(String invariantName) { if (m_features == null) { m_features = AppDomain.CurrentDomain.GetAssemblies() .Where(a => !a.IsDynamic) .SelectMany(a => a.GetManifestResourceNames().Where(n => n.ToLower().EndsWith(".sql")).Select(n => { try { var retVal = SqlFeature.Load(a.GetManifestResourceStream(n)); retVal.Scope = retVal.Scope ?? a.FullName; return(retVal); } catch (Exception e) { m_traceSource.TraceError("Could not load {0}: {1}", n, e); return((SqlFeature)null); } })).OfType <IDataFeature>().ToList(); } return(m_features.Where(o => o.InvariantName == invariantName)); }
/// <summary> /// Creates a SqlMigrationTask /// </summary> public SqlMigrationTask(IFeature feature, SqlFeature dbFeature) { this.Feature = feature; this.m_feature = dbFeature; }