CmdExportSqliteDatabase.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6. namespace etoy
  7. {
  8. internal class CmdExportSqliteDatabase : Command
  9. {
  10. protected virtual TableTag AllowedTableTag => TableTag.Client;
  11. protected virtual KeyValueTag AllowedKeyValueTag => KeyValueTag.Client;
  12. protected virtual string DatabaseOutput => Context.Option.ClientDatabaseOutput;
  13. public override string Description => "生成Sqlite DB文件";
  14. private readonly List<Exception> _errors = new List<Exception>();
  15. protected override void OnProcess()
  16. {
  17. if (File.Exists(DatabaseOutput))
  18. File.Delete(DatabaseOutput);
  19. SetProgress(0.1f);
  20. string file = DatabaseOutput.ToPath();
  21. if (File.Exists(file))
  22. File.Delete(file);
  23. var database = new Database(file);
  24. SetProgress(0.5f);
  25. ExportDatabase(database);
  26. database.Dispose();
  27. if (_errors.Count > 0)
  28. {
  29. SetException(new Exception(string.Join('\n', (from e in _errors select $"## ERROR: {e.Message}").ToArray())));
  30. }
  31. else
  32. {
  33. Completed();
  34. }
  35. }
  36. private void ExportDatabase(Database database)
  37. {
  38. database.Exec("VACUUM");
  39. database.Exec("PRAGMA synchronous = OFF");
  40. List<string> sqls = new List<string>();
  41. // Normal Table Create Sql
  42. GetCreateSqls(sqls);
  43. // Normal Table Insert Sql
  44. GetInsertSqls(sqls);
  45. // KeyValue Table Sql
  46. GetKeyValueSqls(sqls);
  47. // Version Table Sql
  48. GetVersionSqls(sqls);
  49. database.Exec("BEGIN TRANSACTION");
  50. foreach (var sql in sqls)
  51. {
  52. try
  53. {
  54. database.Exec(sql);
  55. }
  56. catch (Exception e)
  57. {
  58. _errors.Add(e);
  59. }
  60. }
  61. database.Exec("END TRANSACTION");
  62. }
  63. private void GetCreateSqls(List<string> cmds)
  64. {
  65. foreach (var table in Context.Blackboard.Tables)
  66. {
  67. if (HasTableFlag(table.TableTag))
  68. {
  69. var sb = new StringBuilder();
  70. for (int i = 0, length = table.FieldInfos.Length; i < length; i++)
  71. {
  72. var fieldInfo = table.FieldInfos[i];
  73. if (HasTableFlag(fieldInfo.OutputTag))
  74. {
  75. if (i > 0)
  76. sb.Append(",");
  77. string fieldType = GetSqliteType(fieldInfo.FieldType, fieldInfo.IsRepeated);
  78. string primaryKey = fieldInfo.IsPrimaryKey ? "PRIMARY KEY" : string.Empty;
  79. sb.Append($"\'{fieldInfo.FieldName}\' {fieldType} {primaryKey}".Trim());
  80. }
  81. }
  82. string createSql = $"CREATE TABLE IF NOT EXISTS {table.Name}({sb});";
  83. cmds.Add(createSql);
  84. }
  85. }
  86. }
  87. private void GetInsertSqls(List<string> cmds)
  88. {
  89. var sb = new StringBuilder();
  90. foreach (var table in Context.Blackboard.Tables)
  91. {
  92. if (HasTableFlag(table.TableTag))
  93. {
  94. for (int i = 0, rowCount = table.Rows.Count; i < rowCount; i++)
  95. {
  96. var row = table.Rows[i];
  97. sb.Clear();
  98. sb.Append($"INSERT INTO {table.Name} VALUES");
  99. sb.Append("(");
  100. for (int j = 0, colCount = row.Cells.Count; j < colCount; j++)
  101. {
  102. var cell = row.Cells[j];
  103. if (HasTableFlag(cell.FieldInfo.OutputTag))
  104. {
  105. if (j > 0)
  106. sb.Append(",");
  107. // Call ToSqlString in need
  108. string sqlString = cell.Value.ToSqlString();
  109. if (Context.Blackboard.ContainsMetadataType(cell.FieldInfo.FieldType))
  110. {
  111. sb.Append($"'{sqlString}'");
  112. }
  113. else
  114. {
  115. if (cell.FieldInfo.IsRepeated || cell.FieldInfo.FieldType == FieldTypeDefine.String)
  116. sb.Append($"'{sqlString.Replace("\\n", "\n")}'");
  117. else
  118. sb.Append($"{sqlString}");
  119. }
  120. }
  121. }
  122. sb.Append(");\n");
  123. cmds.Add(sb.ToString());
  124. }
  125. }
  126. }
  127. }
  128. private void GetKeyValueSqls(List<string> cmds)
  129. {
  130. foreach (var table in Context.Blackboard.KeyValueTables)
  131. {
  132. string createSql = $"CREATE TABLE IF NOT EXISTS {table.Name}(key varchar PRIMARY KEY, value varchar);";
  133. cmds.Add(createSql);
  134. foreach (var row in table.Rows)
  135. {
  136. if (!HasKeyValueFlag(row.OutputTag))
  137. continue;
  138. string insertSql = $"INSERT INTO {table.Name} VALUES('{row.Key.ToSqlString()}', '{row.Value.ToSqlString()}');";
  139. cmds.Add(insertSql);
  140. }
  141. }
  142. }
  143. private void GetVersionSqls(List<string> cmds)
  144. {
  145. string versionTableName = "version";
  146. string createSql = $"CREATE TABLE IF NOT EXISTS {versionTableName}(v integer PRIMARY KEY);";
  147. string insertSql = $"INSERT INTO {versionTableName} VALUES('{Context.Blackboard.Version.ToSqlString()}');";
  148. cmds.Add(createSql);
  149. cmds.Add(insertSql);
  150. }
  151. private string GetSqliteType(string fieldType, bool repeated)
  152. {
  153. if (repeated)
  154. {
  155. return SqliteTypeDefine.Varchar;
  156. }
  157. if (fieldType == FieldTypeDefine.Int ||
  158. fieldType == FieldTypeDefine.Boolean)
  159. {
  160. return SqliteTypeDefine.Integer;
  161. }
  162. if (fieldType == FieldTypeDefine.Long)
  163. {
  164. return SqliteTypeDefine.Integer64;
  165. }
  166. if (fieldType == FieldTypeDefine.String)
  167. {
  168. return SqliteTypeDefine.Varchar;
  169. }
  170. if (fieldType == FieldTypeDefine.Float || fieldType == FieldTypeDefine.Double)
  171. {
  172. return SqliteTypeDefine.Float;
  173. }
  174. return SqliteTypeDefine.Varchar;
  175. }
  176. private bool HasTableFlag(TableTag tag)
  177. {
  178. return AllowedTableTag == TableTag.All || tag.HasFlag(AllowedTableTag);
  179. }
  180. private bool HasKeyValueFlag(KeyValueTag tag)
  181. {
  182. return AllowedKeyValueTag == KeyValueTag.All || tag.HasFlag(AllowedKeyValueTag);
  183. }
  184. }
  185. }