Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

111 lignes
3.9KB

  1. using System.Globalization;
  2. namespace Campaign_Tracker.Server.LegacyData.Schema;
  3. /// <summary>
  4. /// Parses the Access schema text dump shipped at
  5. /// <c>Initial Documents/Access_Schema.txt</c> into a strongly-typed
  6. /// <see cref="LegacySchemaBaseline"/> for compatibility checking.
  7. ///
  8. /// File format (one table per block):
  9. /// <code>
  10. /// Table: Contacts
  11. /// ---------------
  12. /// Column: ID Type: 3 Size: Nullable: False
  13. /// Column: EMAIL Type: 130 Size: 255 Nullable: True
  14. /// </code>
  15. /// </summary>
  16. public static class LegacySchemaBaselineParser
  17. {
  18. public static LegacySchemaBaseline ParseFile(string filePath, DateTimeOffset capturedAt)
  19. {
  20. if (!File.Exists(filePath))
  21. {
  22. throw new FileNotFoundException(
  23. $"Legacy schema baseline file not found: {filePath}", filePath);
  24. }
  25. var text = File.ReadAllText(filePath);
  26. return Parse(text, filePath, capturedAt);
  27. }
  28. public static LegacySchemaBaseline Parse(string text, string source, DateTimeOffset capturedAt)
  29. {
  30. var tables = new List<LegacyTableDefinition>();
  31. string? currentTable = null;
  32. var currentColumns = new List<LegacyColumnDefinition>();
  33. foreach (var rawLine in text.Split('\n'))
  34. {
  35. var line = rawLine.TrimEnd('\r').TrimEnd();
  36. if (line.Length == 0) continue;
  37. if (line.All(c => c == '-')) continue;
  38. if (line.StartsWith("Table:", StringComparison.Ordinal))
  39. {
  40. FlushTable(tables, currentTable, currentColumns);
  41. currentTable = line["Table:".Length..].Trim();
  42. currentColumns = new List<LegacyColumnDefinition>();
  43. continue;
  44. }
  45. var trimmed = line.TrimStart();
  46. if (!trimmed.StartsWith("Column:", StringComparison.Ordinal)) continue;
  47. currentColumns.Add(ParseColumn(trimmed));
  48. }
  49. FlushTable(tables, currentTable, currentColumns);
  50. return new LegacySchemaBaseline(tables, source, capturedAt);
  51. }
  52. private static void FlushTable(
  53. List<LegacyTableDefinition> sink,
  54. string? tableName,
  55. List<LegacyColumnDefinition> columns)
  56. {
  57. if (string.IsNullOrWhiteSpace(tableName) || columns.Count == 0) return;
  58. sink.Add(new LegacyTableDefinition(tableName, columns.ToArray()));
  59. }
  60. private static LegacyColumnDefinition ParseColumn(string line)
  61. {
  62. // "Column: NAME Type: 130 Size: 255 Nullable: True"
  63. var name = ReadField(line, "Column:", ["Type:"]);
  64. var typeRaw = ReadField(line, "Type:", ["Size:", "Nullable:"]);
  65. var sizeRaw = ReadField(line, "Size:", ["Nullable:"]);
  66. var nullableRaw = ReadField(line, "Nullable:", []);
  67. if (!int.TryParse(typeRaw, NumberStyles.Integer, CultureInfo.InvariantCulture, out var typeCode))
  68. {
  69. throw new FormatException($"Invalid Type code in column line: {line}");
  70. }
  71. int? size = null;
  72. if (!string.IsNullOrWhiteSpace(sizeRaw) &&
  73. int.TryParse(sizeRaw, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedSize))
  74. {
  75. size = parsedSize;
  76. }
  77. var nullable = string.Equals(nullableRaw, "True", StringComparison.OrdinalIgnoreCase);
  78. return new LegacyColumnDefinition(name, typeCode, size, nullable);
  79. }
  80. private static string ReadField(string line, string label, string[] terminators)
  81. {
  82. var start = line.IndexOf(label, StringComparison.Ordinal);
  83. if (start < 0) return string.Empty;
  84. start += label.Length;
  85. var end = line.Length;
  86. foreach (var terminator in terminators)
  87. {
  88. var t = line.IndexOf(terminator, start, StringComparison.Ordinal);
  89. if (t >= 0 && t < end) end = t;
  90. }
  91. return line[start..end].Trim();
  92. }
  93. }

Powered by TurnKey Linux.