DmDbMaintenance.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.Common;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Text.RegularExpressions;
  8. namespace SqlSugar
  9. {
  10. public class DmDbMaintenance : DbMaintenanceProvider
  11. {
  12. #region DML
  13. protected override string GetDataBaseSql
  14. {
  15. get
  16. {
  17. throw new NotSupportedException();
  18. }
  19. }
  20. protected override string GetColumnInfosByTableNameSql
  21. {
  22. get
  23. {
  24. throw new NotSupportedException();
  25. }
  26. }
  27. protected override string GetTableInfoListSql
  28. {
  29. get
  30. {
  31. return @"SELECT
  32. table_name name,
  33. (select TOP 1 COMMENTS from user_tab_comments where t.table_name=table_name ) as Description
  34. from user_tables t where
  35. table_name!='HELP'
  36. AND table_name NOT LIKE '%$%'
  37. AND table_name NOT LIKE 'LOGMNRC_%'
  38. AND table_name!='LOGMNRP_CTAS_PART_MAP'
  39. AND table_name!='LOGMNR_LOGMNR_BUILDLOG'
  40. AND table_name!='SQLPLUS_PRODUCT_PROFILE'
  41. ";
  42. }
  43. }
  44. protected override string GetViewInfoListSql
  45. {
  46. get
  47. {
  48. return @"select view_name name from user_views
  49. WHERE VIEW_name NOT LIKE '%$%'
  50. AND VIEW_NAME !='PRODUCT_PRIVS'
  51. AND VIEW_NAME NOT LIKE 'MVIEW_%' ";
  52. }
  53. }
  54. #endregion
  55. #region DDL
  56. protected override string IsAnyIndexSql
  57. {
  58. get
  59. {
  60. return "select count(1) from user_ind_columns where upper(index_name)=upper('{0}')";
  61. }
  62. }
  63. protected override string CreateIndexSql
  64. {
  65. get
  66. {
  67. return "CREATE {3} INDEX Index_{0}_{2} ON {0}({1})";
  68. }
  69. }
  70. protected override string AddDefaultValueSql
  71. {
  72. get
  73. {
  74. return "ALTER TABLE {0} MODIFY({1} DEFAULT '{2}')";
  75. }
  76. }
  77. protected override string CreateDataBaseSql
  78. {
  79. get
  80. {
  81. return "CREATE DATABASE {0}";
  82. }
  83. }
  84. protected override string AddPrimaryKeySql
  85. {
  86. get
  87. {
  88. return "ALTER TABLE {0} ADD PRIMARY KEY({2}) /*{1}*/";
  89. }
  90. }
  91. protected override string AddColumnToTableSql
  92. {
  93. get
  94. {
  95. return "ALTER TABLE {0} ADD ({1} {2}{3} {4} {5} {6})";
  96. }
  97. }
  98. protected override string AlterColumnToTableSql
  99. {
  100. get
  101. {
  102. return "ALTER TABLE {0} modify ({1} {2}{3} {4} {5} {6}) ";
  103. }
  104. }
  105. protected override string BackupDataBaseSql
  106. {
  107. get
  108. {
  109. return @"USE master;BACKUP DATABASE {0} TO disk = '{1}'";
  110. }
  111. }
  112. protected override string CreateTableSql
  113. {
  114. get
  115. {
  116. return "CREATE TABLE {0}(\r\n{1} )";
  117. }
  118. }
  119. protected override string CreateTableColumn
  120. {
  121. get
  122. {
  123. return "{0} {1}{2} {3} {4} {5}";
  124. }
  125. }
  126. protected override string TruncateTableSql
  127. {
  128. get
  129. {
  130. return "TRUNCATE TABLE {0}";
  131. }
  132. }
  133. protected override string BackupTableSql
  134. {
  135. get
  136. {
  137. return "create table {1} as select * from {2} where ROWNUM<={0}";
  138. }
  139. }
  140. protected override string DropTableSql
  141. {
  142. get
  143. {
  144. return "DROP TABLE {0}";
  145. }
  146. }
  147. protected override string DropColumnToTableSql
  148. {
  149. get
  150. {
  151. return "ALTER TABLE {0} DROP COLUMN {1}";
  152. }
  153. }
  154. protected override string DropConstraintSql
  155. {
  156. get
  157. {
  158. return "ALTER TABLE {0} DROP CONSTRAINT {1}";
  159. }
  160. }
  161. protected override string RenameColumnSql
  162. {
  163. get
  164. {
  165. return "ALTER TABLE {0} rename column {1} to {2}";
  166. }
  167. }
  168. protected override string AddColumnRemarkSql
  169. {
  170. get
  171. {
  172. return "comment on column {1}.{0} is '{2}'";
  173. }
  174. }
  175. protected override string DeleteColumnRemarkSql
  176. {
  177. get
  178. {
  179. return "comment on column {1}.{0} is ''";
  180. }
  181. }
  182. protected override string IsAnyColumnRemarkSql
  183. {
  184. get
  185. {
  186. return "select * from user_col_comments where Table_Name='{1}' AND COLUMN_NAME='{0}' order by column_name";
  187. }
  188. }
  189. protected override string AddTableRemarkSql
  190. {
  191. get
  192. {
  193. return "comment on table {0} is '{1}'";
  194. }
  195. }
  196. protected override string DeleteTableRemarkSql
  197. {
  198. get
  199. {
  200. return "comment on table {0} is ''";
  201. }
  202. }
  203. protected override string IsAnyTableRemarkSql
  204. {
  205. get
  206. {
  207. return "select * from user_tab_comments where Table_Name='{0}'order by Table_Name";
  208. }
  209. }
  210. protected override string RenameTableSql
  211. {
  212. get
  213. {
  214. return "alter table {0} rename to {1}";
  215. }
  216. }
  217. protected override string IsAnyProcedureSql => throw new NotImplementedException();
  218. #endregion
  219. #region Check
  220. protected override string CheckSystemTablePermissionsSql
  221. {
  222. get
  223. {
  224. return "select t.table_name from user_tables t where rownum=1";
  225. }
  226. }
  227. #endregion
  228. #region Scattered
  229. protected override string CreateTableNull
  230. {
  231. get
  232. {
  233. return " null ";
  234. }
  235. }
  236. protected override string CreateTableNotNull
  237. {
  238. get
  239. {
  240. return " not null ";
  241. }
  242. }
  243. protected override string CreateTablePirmaryKey
  244. {
  245. get
  246. {
  247. return "PRIMARY KEY";
  248. }
  249. }
  250. protected override string CreateTableIdentity
  251. {
  252. get
  253. {
  254. return "IDENTITY(1,1)";
  255. }
  256. }
  257. #endregion
  258. #region Methods
  259. public override bool UpdateColumn(string tableName, DbColumnInfo column)
  260. {
  261. ConvertCreateColumnInfo(column);
  262. var oldColumn = this.Context.DbMaintenance.GetColumnInfosByTableName(tableName, false)
  263. .FirstOrDefault(it => it.DbColumnName.EqualCase(column.DbColumnName));
  264. if (oldColumn != null)
  265. {
  266. if (oldColumn.IsNullable == column.IsNullable)
  267. {
  268. var sql = GetUpdateColumnSqlOnlyType(tableName, column);
  269. this.Context.Ado.ExecuteCommand(sql);
  270. return true;
  271. }
  272. }
  273. return base.UpdateColumn(tableName, column);
  274. }
  275. protected virtual string GetUpdateColumnSqlOnlyType(string tableName, DbColumnInfo columnInfo)
  276. {
  277. string columnName = this.SqlBuilder.GetTranslationColumnName(columnInfo.DbColumnName);
  278. tableName = this.SqlBuilder.GetTranslationTableName(tableName);
  279. string dataSize = GetSize(columnInfo);
  280. string dataType = columnInfo.DataType;
  281. string nullType = "";
  282. string primaryKey = null;
  283. string identity = null;
  284. string result = string.Format(this.AlterColumnToTableSql, tableName, columnName, dataType, dataSize, nullType, primaryKey, identity);
  285. return result;
  286. }
  287. public override List<string> GetDbTypes()
  288. {
  289. var result = this.Context.Ado.SqlQuery<string>(@"SELECT DISTINCT DATA_TYPE
  290. FROM DBA_TAB_COLUMNS
  291. WHERE OWNER = user ");
  292. result.Add("TIMESTAMP");
  293. result.Add("NCLOB");
  294. return result.Distinct().ToList();
  295. }
  296. public override List<string> GetTriggerNames(string tableName)
  297. {
  298. return this.Context.Ado.SqlQuery<string>(@"SELECT trigger_name
  299. FROM all_triggers
  300. WHERE table_name = '" + tableName + "'");
  301. }
  302. public override List<string> GetFuncList()
  303. {
  304. return this.Context.Ado.SqlQuery<string>(" SELECT object_name\r\nFROM all_objects\r\nWHERE object_type = 'FUNCTION' AND owner = USER ");
  305. }
  306. public override bool RenameTable(string oldTableName, string newTableName)
  307. {
  308. oldTableName = SqlBuilder.GetTranslationColumnName(oldTableName);
  309. newTableName = SqlBuilder.GetTranslationColumnName(newTableName);
  310. return base.RenameTable(oldTableName, newTableName);
  311. }
  312. public override List<string> GetIndexList(string tableName)
  313. {
  314. var sql = $"SELECT index_name FROM user_ind_columns\r\nWHERE upper(table_name) = upper('{tableName}')";
  315. return this.Context.Ado.SqlQuery<string>(sql);
  316. }
  317. public override bool AddColumn(string tableName, DbColumnInfo columnInfo)
  318. {
  319. if (columnInfo.DataType == "varchar" && columnInfo.Length == 0)
  320. {
  321. columnInfo.DataType = "varchar2";
  322. columnInfo.Length = 50;
  323. }
  324. return base.AddColumn(tableName, columnInfo);
  325. }
  326. public override bool CreateIndex(string tableName, string[] columnNames, bool isUnique = false)
  327. {
  328. string sql = string.Format(CreateIndexSql, tableName, string.Join(",", columnNames), string.Join("_", columnNames.Select(it => (it + "abc").Substring(0, 3))), isUnique ? "UNIQUE" : "");
  329. this.Context.Ado.ExecuteCommand(sql);
  330. return true;
  331. }
  332. public override bool AddDefaultValue(string tableName, string columnName, string defaultValue)
  333. {
  334. columnName = SqlBuilder.GetTranslationColumnName(columnName);
  335. tableName = SqlBuilder.GetTranslationColumnName(tableName);
  336. if (defaultValue == "''")
  337. {
  338. defaultValue = "";
  339. }
  340. if (defaultValue.ToLower().IsIn("sysdate"))
  341. {
  342. var template = AddDefaultValueSql.Replace("'", "");
  343. string sql = string.Format(template, tableName, columnName, defaultValue);
  344. this.Context.Ado.ExecuteCommand(sql);
  345. return true;
  346. }
  347. else
  348. {
  349. return base.AddDefaultValue(tableName, columnName, defaultValue);
  350. }
  351. }
  352. public override bool CreateDatabase(string databaseDirectory = null)
  353. {
  354. throw new NotSupportedException();
  355. }
  356. public override bool CreateDatabase(string databaseName, string databaseDirectory = null)
  357. {
  358. if (this.Context.Ado.IsValidConnection())
  359. {
  360. return true;
  361. }
  362. Check.ExceptionEasy("dm no support create database ", "达梦不支持建库方法,请写有效连接字符串可以正常运行该方法。");
  363. return true;
  364. }
  365. public override bool AddRemark(EntityInfo entity)
  366. {
  367. var db = this.Context;
  368. var columns = entity.Columns.Where(it => it.IsIgnore == false).ToList();
  369. foreach (var item in columns)
  370. {
  371. if (item.ColumnDescription != null)
  372. {
  373. //column remak
  374. if (db.DbMaintenance.IsAnyColumnRemark(item.DbColumnName.ToUpper(IsUppper), item.DbTableName.ToUpper(IsUppper)))
  375. {
  376. db.DbMaintenance.DeleteColumnRemark(this.SqlBuilder.GetTranslationColumnName(item.DbColumnName), this.SqlBuilder.GetTranslationColumnName(item.DbTableName));
  377. db.DbMaintenance.AddColumnRemark(this.SqlBuilder.GetTranslationColumnName(item.DbColumnName), this.SqlBuilder.GetTranslationColumnName(item.DbTableName), item.ColumnDescription);
  378. }
  379. else
  380. {
  381. db.DbMaintenance.AddColumnRemark(this.SqlBuilder.GetTranslationColumnName(item.DbColumnName), this.SqlBuilder.GetTranslationColumnName(item.DbTableName), item.ColumnDescription);
  382. }
  383. }
  384. }
  385. //table remak
  386. if (entity.TableDescription != null)
  387. {
  388. if (db.DbMaintenance.IsAnyTableRemark(entity.DbTableName))
  389. {
  390. db.DbMaintenance.DeleteTableRemark(SqlBuilder.GetTranslationColumnName(entity.DbTableName));
  391. db.DbMaintenance.AddTableRemark(SqlBuilder.GetTranslationColumnName(entity.DbTableName), entity.TableDescription);
  392. }
  393. else
  394. {
  395. db.DbMaintenance.AddTableRemark(SqlBuilder.GetTranslationColumnName(entity.DbTableName), entity.TableDescription);
  396. }
  397. }
  398. return true;
  399. }
  400. public override List<DbColumnInfo> GetColumnInfosByTableName(string tableName, bool isCache = true)
  401. {
  402. string cacheKey = "DbMaintenanceProvider.GetColumnInfosByTableName." + this.SqlBuilder.GetNoTranslationColumnName(tableName).ToLower();
  403. cacheKey = GetCacheKey(cacheKey);
  404. if (!isCache)
  405. return GetColumnInfosByTableName(tableName);
  406. else
  407. return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey,
  408. () =>
  409. {
  410. return GetColumnInfosByTableName(tableName);
  411. });
  412. }
  413. private List<DbColumnInfo> GetColumnInfosByTableName(string tableName)
  414. {
  415. string sql = "select * from " + SqlBuilder.GetTranslationTableName(tableName) + " WHERE 1=2 ";
  416. if (!this.GetTableInfoList(false).Any(it => it.Name == SqlBuilder.GetTranslationTableName(tableName).TrimStart('\"').TrimEnd('\"')))
  417. {
  418. sql = "select * from \"" + tableName + "\" WHERE 1=2 ";
  419. }
  420. var oldIsEnableLog = this.Context.Ado.IsEnableLogEvent;
  421. this.Context.Ado.IsEnableLogEvent = false;
  422. using(DbDataReader reader = (DbDataReader) this.Context.Ado.GetDataReader(sql))
  423. {
  424. this.Context.Ado.IsEnableLogEvent = oldIsEnableLog;
  425. List<DbColumnInfo> result = new List<DbColumnInfo>();
  426. var schemaTable = reader.GetSchemaTable();
  427. foreach (System.Data.DataRow row in schemaTable.Rows)
  428. {
  429. DbColumnInfo column = new DbColumnInfo()
  430. {
  431. TableName = tableName,
  432. DataType = row["DataType"].ToString().Replace("System.", "").Trim(),
  433. IsNullable = (bool) row["AllowDBNull"],
  434. IsIdentity = (bool) row["IsIdentity"],
  435. ColumnDescription = GetFieldComment(tableName, row["ColumnName"].ToString()),
  436. DbColumnName = row["ColumnName"].ToString(),
  437. //DefaultValue = row["defaultValue"].ToString(),
  438. IsPrimarykey = GetPrimaryKeyByTableNames(tableName).Any(it => it.Equals(row["ColumnName"].ToString(), StringComparison.CurrentCultureIgnoreCase)),
  439. Length = row["ColumnSize"].ObjToInt(),
  440. Scale = row["numericscale"].ObjToInt()
  441. };
  442. result.Add(column);
  443. }
  444. return result;
  445. }
  446. }
  447. private List<string> GetPrimaryKeyByTableNames(string tableName)
  448. {
  449. string cacheKey = "DbMaintenanceProvider.GetPrimaryKeyByTableNames." + this.SqlBuilder.GetNoTranslationColumnName(tableName).ToLower();
  450. cacheKey = GetCacheKey(cacheKey);
  451. return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey,
  452. () =>
  453. {
  454. var oldIsEnableLog = this.Context.Ado.IsEnableLogEvent;
  455. this.Context.Ado.IsEnableLogEvent = false;
  456. string sql = @" select distinct cu.COLUMN_name KEYNAME from user_cons_columns cu, user_constraints au
  457. where cu.constraint_name = au.constraint_name
  458. and au.constraint_type = 'P' and au.table_name = '" + tableName.ToUpper(IsUppper) + @"'";
  459. var pks = this.Context.Ado.SqlQuery<string>(sql);
  460. this.Context.Ado.IsEnableLogEvent = oldIsEnableLog;
  461. return pks;
  462. });
  463. }
  464. public string GetTableComment(string tableName)
  465. {
  466. string cacheKey = "DbMaintenanceProvider.GetTableComment." + tableName;
  467. var comments = this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey,
  468. () =>
  469. {
  470. string sql = "SELECT COMMENTS FROM USER_TAB_COMMENTS WHERE TABLE_NAME =@tableName ORDER BY TABLE_NAME";
  471. var oldIsEnableLog = this.Context.Ado.IsEnableLogEvent;
  472. this.Context.Ado.IsEnableLogEvent = false;
  473. var pks = this.Context.Ado.SqlQuery<string>(sql, new { tableName = tableName.ToUpper(IsUppper) });
  474. this.Context.Ado.IsEnableLogEvent = oldIsEnableLog;
  475. return pks;
  476. });
  477. return comments.HasValue() ? comments.First() : "";
  478. }
  479. public string GetFieldComment(string tableName, string filedName)
  480. {
  481. string cacheKey = "DbMaintenanceProvider.GetFieldComment." + tableName;
  482. var comments = this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey,
  483. () =>
  484. {
  485. string sql = "SELECT TVNAME AS TableName, COLNAME as DbColumnName ,COMMENT$ AS ColumnDescription from SYSCOLUMNCOMMENTS WHERE TVNAME='" + tableName.ToUpper(IsUppper) + "' ORDER BY TVNAME";
  486. var oldIsEnableLog = this.Context.Ado.IsEnableLogEvent;
  487. this.Context.Ado.IsEnableLogEvent = false;
  488. var pks = this.Context.Ado.SqlQuery<DbColumnInfo>(sql);
  489. this.Context.Ado.IsEnableLogEvent = oldIsEnableLog;
  490. return pks;
  491. });
  492. if (comments.HasValue())
  493. {
  494. var comment = comments.FirstOrDefault(it => it.DbColumnName.Equals(filedName, StringComparison.CurrentCultureIgnoreCase));
  495. return comment?.ColumnDescription;
  496. }
  497. else
  498. {
  499. return "";
  500. }
  501. }
  502. public override bool CreateTable(string tableName, List<DbColumnInfo> columns, bool isCreatePrimaryKey = true)
  503. {
  504. if (columns.HasValue())
  505. {
  506. foreach (var item in columns)
  507. {
  508. ConvertCreateColumnInfo(item);
  509. if (item.DbColumnName.Equals("GUID", StringComparison.CurrentCultureIgnoreCase) && item.Length == 0)
  510. {
  511. item.Length = 10;
  512. }
  513. }
  514. }
  515. string sql = GetCreateTableSql(tableName, columns);
  516. //string primaryKeyInfo = null;
  517. if (columns.Any(it => it.IsPrimarykey) && isCreatePrimaryKey)
  518. {
  519. sql= sql.TrimEnd(')')+ string.Format(", Primary key({0})", string.Join(",", columns.Where(it => it.IsPrimarykey).Select(it => this.SqlBuilder.GetTranslationColumnName(it.DbColumnName.ToUpper(IsUppper)))));
  520. sql = sql + ")";
  521. }
  522. //sql = sql.Replace("$PrimaryKey", primaryKeyInfo);
  523. this.Context.Ado.ExecuteCommand(sql);
  524. return true;
  525. }
  526. public static string ExtractSchema(string connectionString)
  527. {
  528. string pattern = @"(?i)(?:^|;)schema=(\w+)";
  529. Match match = Regex.Match(connectionString?.Replace(" ",""), pattern,RegexOptions.IgnoreCase);
  530. return match.Success ? match.Groups[1].Value : null;
  531. }
  532. public override bool IsAnyTable(string tableName, bool isCache = true)
  533. {
  534. var isSchema = this.Context.CurrentConnectionConfig?.ConnectionString?.Replace(" ","")?.ToLower()?.Contains("schema=") == true;
  535. if (isSchema)
  536. {
  537. var schema= ExtractSchema(this.Context.CurrentConnectionConfig?.ConnectionString);
  538. Check.ExceptionEasy(schema == null, "ConnectionString schema format error, please use schema=(\\w+)", "连接字符串schema格式错误,请用schema=(\\w+)");
  539. return this.Context.Ado.GetInt($@"SELECT COUNT(*)
  540. FROM ALL_TABLES t
  541. WHERE upper(t.TABLE_NAME) = upper('{tableName}')
  542. AND upper(t.OWNER) = upper('{schema}')
  543. ") > 0;
  544. }
  545. else {
  546. return base.IsAnyTable(tableName, isCache);
  547. }
  548. }
  549. #endregion
  550. #region Helper
  551. public bool IsUppper
  552. {
  553. get
  554. {
  555. if (this.Context.CurrentConnectionConfig.MoreSettings == null)
  556. {
  557. return true;
  558. }
  559. else
  560. {
  561. return this.Context.CurrentConnectionConfig.MoreSettings.IsAutoToUpper == true;
  562. }
  563. }
  564. }
  565. private static void ConvertCreateColumnInfo(DbColumnInfo x)
  566. {
  567. string[] array = new string[] { "int" };
  568. if (array.Contains(x.DataType?.ToLower()))
  569. {
  570. x.Length = 0;
  571. x.DecimalDigits = 0;
  572. }
  573. }
  574. #endregion
  575. }
  576. }