Skip to content

Commit 4165df5

Browse files
committed
- 完善 强制索引(WithIndex)同时支持 MySql/Oracle/SqlServer/Sqlite;#2130
1 parent 492edb4 commit 4165df5

File tree

1 file changed

+91
-10
lines changed

1 file changed

+91
-10
lines changed

FreeSql/Extensions/FreeSqlGlobalExtensions.cs

Lines changed: 91 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -420,21 +420,102 @@ static TReturn LocalWithIndex<TReturn>(TReturn query, string indexName, Dictiona
420420
case DataType.SqlServer:
421421
case DataType.OdbcSqlServer:
422422
case DataType.CustomSqlServer:
423+
{
424+
var oldalias = selectProvider._aliasRule;
425+
selectProvider._aliasRule = (type, old) =>
426+
{
427+
if (oldalias != null) old = oldalias(type, old);
428+
if (string.IsNullOrWhiteSpace(indexName) == false && type == selectProvider._tables[0].Table.Type) return LocalAppendWithString(old, $"index={indexName}");
429+
if (rule == null) return old;
430+
return rule.TryGetValue(type, out var tryidxName) && string.IsNullOrWhiteSpace(tryidxName) == false ? LocalAppendWithString(old, $"index={tryidxName}") : old;
431+
};
432+
}
433+
break;
434+
case DataType.MySql:
435+
case DataType.OdbcMySql:
436+
case DataType.CustomMySql:
437+
{
438+
var oldalias = selectProvider._aliasRule;
439+
selectProvider._aliasRule = (type, old) =>
440+
{
441+
if (oldalias != null) old = oldalias(type, old);
442+
if (string.IsNullOrWhiteSpace(indexName) == false && type == selectProvider._tables[0].Table.Type) return LocalAppendMySqlIndex(old, indexName);
443+
if (rule == null) return old;
444+
return rule.TryGetValue(type, out var tryidxName) && string.IsNullOrWhiteSpace(tryidxName) == false ? LocalAppendMySqlIndex(old, indexName) : old;
445+
};
446+
}
447+
break;
448+
case DataType.Oracle:
449+
case DataType.OdbcOracle:
450+
case DataType.CustomOracle:
451+
{
452+
var hintParts = new List<string>();
453+
if (!string.IsNullOrEmpty(indexName) && !string.IsNullOrEmpty(selectProvider._tables[0].Alias))
454+
{
455+
string alias = selectProvider._tables[0].Alias;
456+
hintParts.Add($"INDEX({alias} {indexName})");
457+
}
458+
if (rule != null && rule.Count > 0)
459+
{
460+
var tablesMap = selectProvider._tables
461+
.Skip(1)
462+
.Where(t => !string.IsNullOrEmpty(t.Alias) && t.Table?.Type != null)
463+
.ToDictionary(t => t.Table.Type, t => t);
464+
foreach (var indexRule in rule)
465+
{
466+
if (tablesMap.TryGetValue(indexRule.Key, out var tableInfo))
467+
{
468+
string otherIndexName = indexRule.Value;
469+
if (!string.IsNullOrEmpty(otherIndexName))
470+
hintParts.Add($"INDEX({tableInfo.Alias} {otherIndexName})");
471+
}
472+
}
473+
}
474+
if (hintParts.Count > 0)
475+
{
476+
string finalHint = $"/*+ {string.Join(" ", hintParts)} */";
477+
var _select = selectProvider._select;
478+
int selectKeywordIndex = _select.IndexOf("SELECT ", StringComparison.OrdinalIgnoreCase);
479+
if (selectKeywordIndex != -1)
480+
{
481+
int insertionPoint = selectKeywordIndex + "SELECT ".Length;
482+
selectProvider._select = _select.Insert(insertionPoint, $"{finalHint} ");
483+
}
484+
}
485+
}
486+
break;
487+
case DataType.Sqlite:
488+
{
489+
var oldalias = selectProvider._aliasRule;
490+
selectProvider._aliasRule = (type, old) =>
491+
{
492+
if (oldalias != null) old = oldalias(type, old);
493+
if (string.IsNullOrWhiteSpace(indexName) == false && type == selectProvider._tables[0].Table.Type) return LocalAppendSqliteIndex(old, indexName);
494+
if (rule == null) return old;
495+
return rule.TryGetValue(type, out var tryidxName) && string.IsNullOrWhiteSpace(tryidxName) == false ? LocalAppendSqliteIndex(old, indexName) : old;
496+
};
497+
}
423498
break;
424-
default:
425-
return query;
426499
}
427-
var oldalias = selectProvider._aliasRule;
428-
selectProvider._aliasRule = (type, old) =>
429-
{
430-
if (oldalias != null) old = oldalias(type, old);
431-
if (string.IsNullOrWhiteSpace(indexName) == false && type == selectProvider._tables[0].Table.Type) return LocalAppendWithString(old, $"index={indexName}");
432-
if (rule == null) return old;
433-
return rule.TryGetValue(type, out var tryidxName) && string.IsNullOrWhiteSpace(tryidxName) == false ? LocalAppendWithString(old, $"index={tryidxName}") : old;
434-
};
500+
435501
return query;
436502
}
437503
static string LocalAppendWithString(string old, string str) => old?.Contains(" With(") == true ? old.Replace(" With(", $" With({str}, ") : $"{old} With({str})";
504+
static string LocalAppendMySqlIndex(string old, string indexName)
505+
{
506+
if (string.IsNullOrEmpty(old)) return $"FORCE INDEX({indexName})";
507+
int forceIndexPosition = old.IndexOf("FORCE INDEX(", StringComparison.OrdinalIgnoreCase);
508+
if (forceIndexPosition == -1) return $"{old} FORCE INDEX({indexName})";
509+
int closingParenPosition = old.IndexOf(')', forceIndexPosition);
510+
if (closingParenPosition != -1) return old.Insert(closingParenPosition, $",{indexName}");
511+
return old;
512+
}
513+
static string LocalAppendSqliteIndex(string old, string indexName)
514+
{
515+
if (string.IsNullOrEmpty(old)) return $"INDEXED BY {indexName}";
516+
if (old.IndexOf("INDEXED BY", StringComparison.OrdinalIgnoreCase) != -1) return old;
517+
return $"{old} INDEXED BY {indexName}";
518+
}
438519

439520
/// <summary>
440521
/// 设置全局 SqlServer: with(nolock)<para></para>

0 commit comments

Comments
 (0)