Last active
October 2, 2021 16:30
-
-
Save bgrainger/791cecb647d514a9dd2f3d83b2387e49 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
async Task Main() | |
{ | |
var httpClient = new HttpClient(); | |
var html57 = await (await httpClient.GetAsync("https://dev.mysql.com/doc/mysql-errors/5.7/en/server-error-reference.html")).Content.ReadAsStringAsync(); | |
var html8 = await (await httpClient.GetAsync("https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html")).Content.ReadAsStringAsync(); | |
var valueNames = new Dictionary<int, string>(); | |
foreach (MySqlErrorCode value in Enum.GetValues(typeof(MySqlErrorCode))) | |
{ | |
var intValue = (int)value; | |
valueNames[(int)value] = value.ToString(); | |
} | |
var allErrors = new Dictionary<int, (string Name, string Description)>(); | |
ReadErrorsFromHtml(allErrors, valueNames, html57); | |
ReadErrorsFromHtml(allErrors, valueNames, html8); | |
const string fileName = @"MySqlErrorCode.g.cs"; | |
using (var writer = new StreamWriter(fileName)) | |
{ | |
writer.WriteLine(@"namespace MySqlConnector; | |
/// <summary> | |
/// MySQL Server error codes. Taken from <a href=""https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html"">Server Error Codes and Messages</a>. | |
/// </summary> | |
[System.CodeDom.Compiler.GeneratedCode(""https://gist.github.com/bgrainger/791cecb647d514a9dd2f3d83b2387e49"", ""5"")] | |
public enum MySqlErrorCode | |
{ | |
DelimiterNotSupported = -3, | |
/// <summary> | |
/// Not all rows from the source supplied to <see cref=""MySqlBulkCopy""/> were copied to <see cref=""MySqlBulkCopy.DestinationTableName""/>. | |
/// </summary> | |
BulkCopyFailed = -2, | |
/// <summary> | |
/// The timeout period specified by <see cref=""MySqlCommand.CommandTimeout""/> elapsed before the operation completed. | |
/// </summary> | |
CommandTimeoutExpired = -1,"); | |
foreach (var kvp in allErrors.OrderBy(x => x.Key)) | |
{ | |
writer.WriteLine(); | |
writer.Write($@" /// <summary> | |
/// {kvp.Value.Description} | |
/// </summary> | |
{kvp.Value.Name} = {kvp.Key}, | |
"); | |
} | |
writer.WriteLine(@"}"); | |
} | |
File.WriteAllBytes(fileName, File.ReadAllBytes(fileName).Where(x => x != 0x0D).ToArray()); | |
} | |
void ReadErrorsFromHtml(Dictionary<int, (string, string)> allErrors, Dictionary<int, string> valueNames, string html) | |
{ | |
var messageOverrides = new Dictionary<int, string> | |
{ | |
{ 1064, "You have an error in your SQL syntax" }, | |
{ 1317, "Query execution was interrupted" }, | |
}; | |
var seenErrors = new HashSet<int>(); | |
using (var reader = new StringReader(html)) | |
{ | |
int errorCode = 0; | |
string errorName = null; | |
string errorMessage = null; | |
string line; | |
while ((line = reader.ReadLine()) != null) | |
{ | |
if (errorName != null) | |
{ | |
if (line.StartsWith(" </p>", StringComparison.OrdinalIgnoreCase)) | |
{ | |
if (errorMessage != null) | |
{ | |
if (seenErrors.Add(errorCode)) | |
{ | |
errorMessage = Regex.Replace(errorMessage, @"\s+", " ").Replace(" Message: ", ""); | |
// try to match official name if known | |
if (!valueNames.TryGetValue(errorCode, out var valueName)) | |
{ | |
// otherwise synthesise a name by CamelCasing the error code | |
valueName = Regex.Replace(errorName, @"^(WARN|ER)_", "_") + "_"; | |
valueName = Regex.Replace(valueName, @"(?<!_)[A-Z]", x => x.Groups[0].Value.ToLowerInvariant()); | |
// replace some error code abbreviations with spelled-out words for the enum value name | |
valueName = valueName.Replace("Cant_", "Cannot_"); | |
valueName = valueName.Replace("Cond_Item_", "ConditionItem_"); | |
valueName = valueName.Replace("Dup_", "Duplicate_"); | |
valueName = valueName.Replace("Fk_", "ForeignKey_"); | |
valueName = valueName.Replace("Ft_", "FullText_"); | |
valueName = valueName.Replace("Jt_", "JsonTable_"); | |
valueName = valueName.Replace("Tf_", "TableFunction_"); | |
valueName = valueName.Replace("Io_", "IO_"); | |
valueName = valueName.Replace("Serverid_", "ServerId_"); | |
valueName = valueName.Replace("Stmt_", "Statement_"); | |
valueName = valueName.Replace("Vcpu_", "VCpu_"); | |
valueName = valueName.Replace("_", ""); | |
} | |
// NOTE: 'errorMessage' contains a human-readable error message, but it was not authored by us; use a simple description for the comment instead. | |
string description; | |
if (messageOverrides.TryGetValue(errorCode, out var messageOverride)) | |
description = $"{messageOverride} ({errorName})."; | |
else | |
description = errorName; | |
if (!allErrors.ContainsKey(errorCode)) | |
allErrors.Add(errorCode, (valueName, description)); | |
} | |
errorCode = 0; | |
errorName = null; | |
errorMessage = null; | |
} | |
} | |
else | |
{ | |
errorMessage = errorMessage + line; | |
} | |
} | |
else | |
{ | |
Match match; | |
if ((match = Regex.Match(line, @"Error number: <code class=""literal"">([0-9]+)</code>; Symbol:")).Success) | |
{ | |
errorCode = int.Parse(match.Groups[1].Value); | |
errorName = errorMessage = null; | |
} | |
else if ((match = Regex.Match(line, @"<a class=""link"" href=""server-error-reference.html#[^""]+""><code class=""literal"">(.*?)</code></a>")).Success) | |
{ | |
errorName = match.Groups[1].Value; | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@bgrainger Looks like they moved the error list to https://dev.mysql.com/doc/refman/5.7/en/server-error-reference.html