Skip to content

Commit 567304d

Browse files
committed
[Database] Query generator improvements: bulk insert, 'try' operations
1 parent 7b48948 commit 567304d

File tree

62 files changed

+1738
-292
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+1738
-292
lines changed

DatabaseTester/Program.cs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@
1818
using WDE.DatabaseEditors.Factories;
1919
using WDE.DatabaseEditors.Loaders;
2020
using WDE.DatabaseEditors.Services;
21+
using WDE.Module;
2122
using WDE.MySqlDatabaseCommon.Database;
2223
using WDE.MySqlDatabaseCommon.Providers;
2324
using WDE.MySqlDatabaseCommon.Services;
2425
using WDE.QueryGenerators;
26+
using WDE.QueryGenerators.Base;
2527
using WDE.SqlInterpreter;
28+
using WDE.SqlQueryGenerator;
2629
using WDE.Trinity;
2730
using WDE.TrinityMySqlDatabase;
2831
using WDE.TrinityMySqlDatabase.Data;
@@ -138,6 +141,19 @@ public static async Task<int> Test<T>(string[] args, params ICoreVersion[] cores
138141

139142

140143
var ioc = new UnityContainer().AddExtension(new Diagnostic());
144+
145+
var queryGenerators = typeof(T).Assembly.GetTypes()
146+
.Where(type => type.GetInterfaces().Where(i => i.IsGenericType)
147+
.Select(i => i.GetGenericTypeDefinition())
148+
.Any(i => i == typeof(IInsertQueryProvider<>) ||
149+
i == typeof(IDeleteQueryProvider<>) ||
150+
i == typeof(IUpdateQueryProvider<>)));
151+
foreach (var queryGenerator in queryGenerators)
152+
{
153+
foreach (var @interface in queryGenerator.GetInterfaces())
154+
ioc.RegisterSingleton(@interface, queryGenerator);
155+
}
156+
141157
ioc.RegisterInstance<IContainerProvider>(new UnityContainerProvider(ioc));
142158
ioc.RegisterInstance<IMessageBoxService>(new ConsoleMessageBoxService());
143159
ioc.RegisterInstance<IWorldDatabaseSettingsProvider>(dbSettings);
@@ -149,6 +165,7 @@ public static async Task<int> Test<T>(string[] args, params ICoreVersion[] cores
149165
ioc.RegisterInstance<ITaskRunner>(new SyncTaskRunner());
150166
ioc.RegisterInstance<IStatusBar>(Substitute.For<IStatusBar>());
151167
ioc.RegisterInstance<IParameterFactory>(Substitute.For<IParameterFactory>());
168+
ioc.RegisterInstance<IUserSettings>(Substitute.For<IUserSettings>());
152169

153170
ioc.RegisterInstance<IMySqlWorldConnectionStringProvider>(databaseConn);
154171
ioc.RegisterInstance<IMainThread>(new SyncMainThread());
@@ -169,7 +186,7 @@ public static async Task<int> Test<T>(string[] args, params ICoreVersion[] cores
169186
var queryGeneratorModule = new QueryGeneratorModule();
170187
queryGeneratorModule.InitializeCore(core.Tag);
171188
queryGeneratorModule.RegisterTypes(new UnityContainerRegistry(ioc));
172-
189+
173190
var worldDb = ioc.Resolve<T>();
174191
ioc.RegisterInstance<IDatabaseProvider>(worldDb);
175192
ioc.RegisterInstance<ICachedDatabaseProvider>(worldDb);
@@ -193,11 +210,22 @@ public static async Task<int> Test<T>(string[] args, params ICoreVersion[] cores
193210
await executor.ExecuteSql($"ALTER TABLE `{tableName}` ENGINE = InnoDB");
194211
}
195212

196-
foreach (var query in tester.Generate().Where(x => x != null))
213+
foreach (var queryGenerator in tester.Generate())
197214
{
215+
IQuery query;
198216
try
199217
{
200-
await executor.ExecuteSql(query!);
218+
query = queryGenerator();
219+
}
220+
catch (TableNotSupportedException e)
221+
{
222+
Console.WriteLine("Skipping table: " + e.TableName + " because it is not supported by the selected core.");
223+
continue;
224+
}
225+
226+
try
227+
{
228+
await executor.ExecuteSql(query, true);
201229
}
202230
catch (Exception e)
203231
{
@@ -247,12 +275,15 @@ public static async Task<int> Test<T>(string[] args, params ICoreVersion[] cores
247275
await worldDb.FindSmartScriptLinesBy(new (IDatabaseProvider.SmartLinePropertyType what, int whatValue, int parameterIndex, long valueToSearch)[] { (IDatabaseProvider.SmartLinePropertyType.Action, 0, 0, 0) });
248276

249277
foreach (var type in Enum.GetValues<EventScriptType>())
278+
{
279+
Console.WriteLine($"GetEventScript({type})");
250280
await worldDb.GetEventScript(type, 0);
281+
}
251282

252283
return 0;
253284
}
254285

255-
private static void FixCurrentDirectory()
286+
public static void FixCurrentDirectory()
256287
{
257288
var path = Assembly.GetExecutingAssembly().Location;
258289
if (string.IsNullOrEmpty(path))

DatabaseTester/QueryGeneratorTester.cs

Lines changed: 101 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,28 @@ public class QueryGeneratorTester
1515
private readonly IQueryGenerator<QuestChainDiff> questChain;
1616
private readonly IQueryGenerator<CreatureDiff> creatureDiff;
1717
private readonly IQueryGenerator<GameObjectDiff> gameobjectDiff;
18+
private readonly IQueryGenerator<ICreatureText> creatureText;
19+
private readonly IQueryGenerator<IGossipMenuOption> gossipMenuOption;
20+
private readonly IQueryGenerator<IGossipMenuLine> gossipMenu;
21+
private readonly IQueryGenerator<CreatureGossipUpdate> creatureTemplateDiff;
22+
private readonly IQueryGenerator<IPointOfInterest> pointOfInterest;
23+
private readonly IQueryGenerator<INpcTextFull> npcTextInsert;
24+
private readonly IQueryGenerator<INpcText> npcTextDelete;
1825

1926
public QueryGeneratorTester(IQueryGenerator<CreatureSpawnModelEssentials> creature,
2027
IQueryGenerator<GameObjectSpawnModelEssentials> gameobject,
2128
IQueryGenerator<ISpawnGroupTemplate> spawnGroupTemplate,
2229
IQueryGenerator<ISpawnGroupSpawn> spawnGroupSpawn,
2330
IQueryGenerator<QuestChainDiff> questChain,
2431
IQueryGenerator<CreatureDiff> creatureDiff,
25-
IQueryGenerator<GameObjectDiff> gameobjectDiff)
32+
IQueryGenerator<GameObjectDiff> gameobjectDiff,
33+
IQueryGenerator<ICreatureText> creatureText,
34+
IQueryGenerator<IGossipMenuOption> gossipMenuOption,
35+
IQueryGenerator<IGossipMenuLine> gossipMenu,
36+
IQueryGenerator<CreatureGossipUpdate> creatureTemplateDiff,
37+
IQueryGenerator<IPointOfInterest> pointOfInterest,
38+
IQueryGenerator<INpcTextFull> npcTextInsert,
39+
IQueryGenerator<INpcText> npcTextDelete)
2640
{
2741
this.creature = creature;
2842
this.gameobject = gameobject;
@@ -31,6 +45,13 @@ public QueryGeneratorTester(IQueryGenerator<CreatureSpawnModelEssentials> creatu
3145
this.questChain = questChain;
3246
this.creatureDiff = creatureDiff;
3347
this.gameobjectDiff = gameobjectDiff;
48+
this.creatureText = creatureText;
49+
this.gossipMenuOption = gossipMenuOption;
50+
this.gossipMenu = gossipMenu;
51+
this.creatureTemplateDiff = creatureTemplateDiff;
52+
this.pointOfInterest = pointOfInterest;
53+
this.npcTextInsert = npcTextInsert;
54+
this.npcTextDelete = npcTextDelete;
3455
}
3556

3657
public IEnumerable<string?> Tables()
@@ -39,64 +60,120 @@ public QueryGeneratorTester(IQueryGenerator<CreatureSpawnModelEssentials> creatu
3960
yield return gameobject.TableName;
4061
yield return spawnGroupTemplate.TableName;
4162
yield return spawnGroupSpawn.TableName;
63+
yield return creatureText.TableName;
64+
yield return gossipMenuOption.TableName;
65+
yield return gossipMenu.TableName;
66+
yield return creatureTemplateDiff.TableName;
67+
yield return pointOfInterest.TableName;
68+
yield return npcTextInsert.TableName;
4269
}
4370

44-
public IEnumerable<IQuery?> Generate()
71+
public IEnumerable<Func<IQuery>> Generate()
4572
{
46-
yield return creature.Insert(new CreatureSpawnModelEssentials()
73+
yield return () => gossipMenuOption.Insert(new AbstractGossipMenuOption()
4774
{
48-
Guid = int.MaxValue - 1
75+
MenuId = 1,
4976
});
50-
yield return gameobject.Insert(new GameObjectSpawnModelEssentials()
77+
yield return () => gossipMenuOption.Delete(new AbstractGossipMenuOption()
5178
{
52-
Guid = int.MaxValue - 1
79+
MenuId = 1
5380
});
54-
yield return creature.Delete(new CreatureSpawnModelEssentials()
81+
yield return () => gossipMenu.Insert(new AbstractGossipMenuLine()
5582
{
56-
Guid = int.MaxValue - 1
83+
MenuId = 1,
5784
});
58-
yield return gameobject.Delete(new GameObjectSpawnModelEssentials()
85+
yield return () => gossipMenu.Delete(new AbstractGossipMenuLine()
5986
{
60-
Guid = int.MaxValue - 1
87+
MenuId = 1
88+
});
89+
yield return () => creature.Insert(new CreatureSpawnModelEssentials()
90+
{
91+
Guid = 0xFFFFFF - 1,
92+
Entry = 1
93+
});
94+
yield return () => creatureDiff.Update(new CreatureDiff()
95+
{
96+
Guid = 0xFFFFFF - 1,
97+
Position = Vector3.Zero,
98+
Orientation = 0
99+
});
100+
yield return () => gameobject.Insert(new GameObjectSpawnModelEssentials()
101+
{
102+
Guid = 0xFFFFFF - 1,
103+
Entry = 29
104+
});
105+
yield return () => creature.Delete(new CreatureSpawnModelEssentials()
106+
{
107+
Guid = 0xFFFFFF - 1
108+
});
109+
yield return () => gameobjectDiff.Update(new GameObjectDiff()
110+
{
111+
Guid = 0xFFFFFF - 1,
112+
Position = Vector3.Zero,
113+
Orientation = 0,
114+
Rotation = Quaternion.Identity
115+
});
116+
yield return () => gameobject.Delete(new GameObjectSpawnModelEssentials()
117+
{
118+
Guid = 0xFFFFFF - 1
61119
});
62-
yield return spawnGroupTemplate.Insert(new AbstractSpawnGroupTemplate()
120+
yield return () => spawnGroupTemplate.Insert(new AbstractSpawnGroupTemplate()
63121
{
64122
Id = int.MaxValue - 1
65123
});
66-
yield return spawnGroupSpawn.Insert(new AbstractSpawnGroupSpawn()
124+
yield return () => spawnGroupSpawn.Insert(new AbstractSpawnGroupSpawn()
67125
{
68126
TemplateId = int.MaxValue - 1,
69127
Guid = int.MaxValue - 1
70128
});
71-
yield return spawnGroupTemplate.Delete(new AbstractSpawnGroupTemplate()
129+
yield return () => spawnGroupTemplate.Delete(new AbstractSpawnGroupTemplate()
72130
{
73131
Id = int.MaxValue - 1
74132
});
75-
yield return spawnGroupSpawn.Delete(new AbstractSpawnGroupSpawn()
133+
yield return () => spawnGroupSpawn.Delete(new AbstractSpawnGroupSpawn()
76134
{
77135
TemplateId = int.MaxValue - 1,
78136
Guid = int.MaxValue - 1
79137
});
80-
yield return questChain.Update(new QuestChainDiff()
138+
yield return () => questChain.Update(new QuestChainDiff()
81139
{
82140
Id = int.MaxValue - 1,
83141
BreadcrumbQuestId = 1,
84142
ExclusiveGroup = -2,
85143
NextQuestId = 3,
86144
PrevQuestId = -1
87145
});
88-
yield return creatureDiff.Update(new CreatureDiff()
146+
yield return () => creatureText.Insert(new AbstractCreatureText()
89147
{
90-
Guid = int.MaxValue - 1,
91-
Position = Vector3.Zero,
92-
Orientation = 0
148+
CreatureId = 1,
149+
GroupId = byte.MaxValue - 1,
150+
Id = byte.MaxValue - 1,
151+
Text = "abc"
93152
});
94-
yield return gameobjectDiff.Update(new GameObjectDiff()
153+
yield return () => creatureText.Delete(new AbstractCreatureText()
95154
{
96-
Guid = int.MaxValue - 1,
97-
Position = Vector3.Zero,
98-
Orientation = 0,
99-
Rotation = Quaternion.Identity
155+
CreatureId = 0xFFFFFF - 1
156+
});
157+
yield return () => creatureTemplateDiff.Update(new CreatureGossipUpdate()
158+
{
159+
Entry = 1,
160+
GossipMenuId = 1
161+
});
162+
yield return () => pointOfInterest.Insert(new AbstractPointOfInterest()
163+
{
164+
Id = 0xFFFFFF - 1
165+
});
166+
yield return () => pointOfInterest.Delete(new AbstractPointOfInterest()
167+
{
168+
Id = 0xFFFFFF - 1
169+
});
170+
yield return () => npcTextInsert.Insert(new AbstractNpcTextFull()
171+
{
172+
Id = 0xFFFFFF - 10
173+
});
174+
yield return () => npcTextDelete.Delete(new AbstractNpcText()
175+
{
176+
Id = 0xFFFFFF - 10
100177
});
101178
}
102179
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using WDE.SqlQueryGenerator;
2+
3+
namespace WDE.QueryGenerators.Base;
4+
5+
public abstract class BaseInsertQueryProvider<T> : IInsertQueryProvider<T>
6+
{
7+
public IQuery Insert(T t)
8+
{
9+
return Queries.Table(TableName).Insert(Convert(t));
10+
}
11+
12+
public IQuery BulkInsert(IReadOnlyCollection<T> collection)
13+
{
14+
return Queries.Table(TableName).BulkInsert(collection.Select(Convert));
15+
}
16+
17+
protected abstract object Convert(T obj);
18+
19+
public abstract string TableName { get; }
20+
}

Modules/WDE.QueryGenerators/Base/IInsertQueryProvider.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace WDE.QueryGenerators.Base;
77
public interface IInsertQueryProvider<T>
88
{
99
IQuery Insert(T t);
10+
IQuery BulkInsert(IReadOnlyCollection<T> collection);
1011
string TableName { get; }
1112
int Priority => 0;
1213
}
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
using WDE.SqlQueryGenerator;
2+
using Extensions = AvaloniaStyles.Controls.Extensions;
23

34
namespace WDE.QueryGenerators.Base;
45

5-
public interface IQueryGenerator<R>
6+
public interface IQueryGenerator<T>
67
{
7-
IQuery? Insert(R element);
8-
IQuery? Delete(R element);
9-
IQuery? Update(R element);
8+
IQuery? TryInsert(T element);
9+
IQuery? TryBulkInsert(IReadOnlyCollection<T> elements);
10+
IQuery? TryDelete(T element);
11+
IQuery? TryUpdate(T element);
1012
string? TableName { get; }
1113
}

Modules/WDE.QueryGenerators/Base/IUpdateQueryProvider.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ namespace WDE.QueryGenerators.Base;
77
public interface IUpdateQueryProvider<T>
88
{
99
IQuery Update(T diff);
10+
string TableName { get; }
1011
int Priority => 0;
1112
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using WDE.Module.Attributes;
2+
using WDE.SqlQueryGenerator;
3+
4+
namespace WDE.QueryGenerators.Base;
5+
6+
[AutoRegister]
7+
[SingleInstance]
8+
public abstract class NotSupportedQueryProvider<T> : IInsertQueryProvider<T>, IDeleteQueryProvider<T>, IUpdateQueryProvider<T>
9+
{
10+
public abstract string TableName { get; }
11+
12+
public IQuery Insert(T t) => throw new TableNotSupportedException(TableName);
13+
14+
public IQuery BulkInsert(IReadOnlyCollection<T> collection) => throw new TableNotSupportedException(TableName);
15+
16+
public IQuery Delete(T t) => throw new TableNotSupportedException(TableName);
17+
18+
public IQuery Update(T diff) => throw new TableNotSupportedException(TableName);
19+
}
20+
21+
public class TableNotSupportedException : Exception
22+
{
23+
public string TableName { get; }
24+
25+
public TableNotSupportedException(string tableName) : base("Currently selected database doesn't support table " + tableName)
26+
{
27+
TableName = tableName;
28+
}
29+
}

Modules/WDE.QueryGenerators/Base/QueryGenerator.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@ public QueryGenerator(IEnumerable<IInsertQueryProvider<R>> insertProviders,
2222
Console.WriteLine("Couldn't find a provider for " + typeof(R));
2323
}
2424

25-
public IQuery? Insert(R element) => insertProvider?.Insert(element);
26-
public IQuery? Delete(R element) => deleteProvider?.Delete(element);
27-
public IQuery? Update(R element) => updateProvider?.Update(element);
25+
public IQuery? TryInsert(R element) => insertProvider?.Insert(element);
26+
public IQuery? TryBulkInsert(IReadOnlyCollection<R> elements) => insertProvider?.BulkInsert(elements);
27+
28+
public IQuery? TryDelete(R element) => deleteProvider?.Delete(element);
29+
public IQuery? TryUpdate(R element) => updateProvider?.Update(element);
2830

2931
public string? TableName => insertProvider?.TableName;
3032
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace WDE.QueryGenerators.Base;
2+
3+
public class QueryGeneratorException<T> : Exception
4+
{
5+
public QueryGeneratorException(string updateName) : base($"{updateName} query generator for " + typeof(T).Name + " not found for selected core version") { }
6+
}

0 commit comments

Comments
 (0)