Add MariaDB support (#156)

* Fixed startup db check

* Relation tables are created automatically for IGDB metadata

* Removed JSON dependency from filters

* Removed JSON searches from Game library queries

* Gaseous now runs without error on MariaDB

* Fixed static database name bug

* Updated docker files and README
This commit is contained in:
Michael Green
2023-10-13 20:59:53 -07:00
committed by GitHub
parent 1ade1922df
commit b0e74a2010
41 changed files with 282 additions and 170 deletions

View File

@@ -16,11 +16,12 @@ If you expose the server to the internet, **you do so at your own risk**.
![Emulator](./screenshots/Emulator.png)
## Requirements
* MySQL Server 8+*
* MariaDB 11.1.2 or MySQL Server 8+
* These are the database versions Gaseous has been tested and developed against. Your mileage may vary with earlier versions.
* Currently MariaDB is the preferred database server, while MySQL will continue to be supported for existing users (they should be interchangable).
* Note that due to the earlier database schema using MySQL specific features, moving to MariaDB from MySQL will require rebuilding your database from scratch. The "Library Scan" background task can be used to re-import all titles.
* Internet Game Database API Key. See: https://api-docs.igdb.com/#account-creation
***Note**: MariaDB is currently not supported as Gaseous uses features present only in MySQL. This is being tracked in https://github.com/gaseous-project/gaseous-server/issues/93
## Third Party Projects
The following projects are used by Gaseous
* https://dotnet.microsoft.com/en-us/apps/aspnet
@@ -66,7 +67,7 @@ When Gaseous-Server is started for the first time, it creates a configuration fi
},
"LoggingConfiguration": {
"DebugLogging": false,
"LogFormat": "text"
"LogRetention": 7
}
}
@@ -75,7 +76,7 @@ When Gaseous-Server is started for the first time, it creates a configuration fi
## Docker
### Deploy with the prebuilt Docker image
Dockerfile and docker-compose.yml files have been provided to make deployment of the server as easy as possible.
1. Download the docker-compose.yml file
1. Download the docker-compose-{database}.yml file for the database type you would like to use.
2. Open the docker-compose.yml file and edit the igdbclientid and igdbclientsecret to the values retrieved from your IGDB account
3. Run the command ```docker-compose up -d```
4. Connect to the host on port 5198
@@ -85,13 +86,13 @@ Dockerfile and docker-compose-build.yml files have been provided to make deploym
1. Clone the repo with ```git clone https://github.com/gaseous-project/gaseous-server.git```
2. Change into the gaseous-server directory
3. Clone the submodules with the command ```git submodule update --init```
4. Open the docker-compose-build.yml file and edit the igdbclientid and igdbclientsecret to the values retrieved from your IGDB account
5. Run the command ```docker-compose --file docker-compose-build.yml up -d```
4. Open the docker-compose-{database}-build.yml file and edit the igdbclientid and igdbclientsecret to the values retrieved from your IGDB account
5. Run the command ```docker-compose --file docker-compose-{database}-build.yml up -d```
6. Connect to the host on port 5198
## Source
### Build and deploy
1. Install and configure a MySQL instance
1. Install and configure a MariaDB or MySQL instance - this is beyond the scope of this document
2. Install the dotnet 7.0 packages appropriate for your operating system
* See: https://learn.microsoft.com/en-us/dotnet/core/install/linux
3. Create a database user with permission to create a databse. Gaseous will create the new database and apply the database schema on it's first startup.

View File

@@ -0,0 +1,39 @@
version: '2'
services:
gaseous-server:
container_name: gaseous-server
build:
context: ./
restart: unless-stopped
networks:
- gaseous
depends_on:
- gsdb
ports:
- 5198:80
volumes:
- gs:/root/.gaseous-server
environment:
- dbhost=gsdb
- dbuser=root
- dbpass=gaseous
- igdbclientid=<clientid>
- igdbclientsecret=<clientsecret>
gsdb:
container_name: gsdb
image: mariadb
restart: unless-stopped
networks:
- gaseous
volumes:
- gsdb:/var/lib/mysql
environment:
- MARIADB_ROOT_PASSWORD=gaseous
- MARIADB_USER=gaseous
- MARIADB_PASSWORD=gaseous
networks:
gaseous:
driver: bridge
volumes:
gs:
gsdb:

View File

@@ -0,0 +1,38 @@
version: '2'
services:
gaseous-server:
container_name: gaseous-server
image: gaseousgames/gaseousserver:latest
restart: unless-stopped
networks:
- gaseous
depends_on:
- gsdb
ports:
- 5198:80
volumes:
- gs:/root/.gaseous-server
environment:
- dbhost=gsdb
- dbuser=root
- dbpass=gaseous
- igdbclientid=<clientid>
- igdbclientsecret=<clientsecret>
gsdb:
container_name: gsdb
image: mariadb
restart: unless-stopped
networks:
- gaseous
volumes:
- gsdb:/var/lib/mysql
environment:
- MARIADB_ROOT_PASSWORD=gaseous
- MARIADB_USER=gaseous
- MARIADB_PASSWORD=gaseous
networks:
gaseous:
driver: bridge
volumes:
gs:
gsdb:

View File

@@ -7,8 +7,6 @@ using System.Threading.Tasks;
using gaseous_server.Classes.Metadata;
using gaseous_tools;
using IGDB.Models;
using MySqlX.XDevAPI;
using Org.BouncyCastle.Utilities.IO.Pem;
using static gaseous_server.Classes.Metadata.Games;
namespace gaseous_server.Classes

View File

@@ -3,7 +3,6 @@ using System.Reflection;
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata

View File

@@ -2,7 +2,6 @@
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata

View File

@@ -2,7 +2,6 @@
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata

View File

@@ -2,7 +2,6 @@
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata

View File

@@ -2,7 +2,6 @@
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata

View File

@@ -2,7 +2,6 @@
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata

View File

@@ -2,7 +2,6 @@
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata

View File

@@ -2,7 +2,6 @@
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata

View File

@@ -2,7 +2,6 @@
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata

View File

@@ -2,7 +2,6 @@
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata

View File

@@ -2,7 +2,6 @@
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata

View File

@@ -106,6 +106,7 @@ namespace gaseous_server.Classes.Metadata
{
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
UpdateSubClasses(returnValue, getAllMetadata, followSubGames);
}
catch (Exception ex)
{
@@ -122,11 +123,53 @@ namespace gaseous_server.Classes.Metadata
private static void UpdateSubClasses(Game Game, bool getAllMetadata, bool followSubGames)
{
// required metadata
if (Game.Cover != null)
{
Cover GameCover = Covers.GetCover(Game.Cover.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game));
}
if (Game.Genres != null)
{
foreach (long GenreId in Game.Genres.Ids)
{
Genre GameGenre = Genres.GetGenres(GenreId);
}
}
if (Game.GameModes != null)
{
foreach (long gameModeId in Game.GameModes.Ids)
{
GameMode gameMode = GameModes.GetGame_Modes(gameModeId);
}
}
if (Game.MultiplayerModes != null)
{
foreach (long multiplayerModeId in Game.MultiplayerModes.Ids)
{
MultiplayerMode multiplayerMode = MultiplayerModes.GetGame_MultiplayerModes(multiplayerModeId);
}
}
if (Game.PlayerPerspectives != null)
{
foreach (long PerspectiveId in Game.PlayerPerspectives.Ids)
{
PlayerPerspective GamePlayPerspective = PlayerPerspectives.GetGame_PlayerPerspectives(PerspectiveId);
}
}
if (Game.Themes != null)
{
foreach (long ThemeId in Game.Themes.Ids)
{
Theme GameTheme = Themes.GetGame_Themes(ThemeId);
}
}
// optional metadata - usually downloaded as needed
if (getAllMetadata == true)
{
if (Game.AgeRatings != null)
@@ -196,14 +239,6 @@ namespace gaseous_server.Classes.Metadata
}
}
if (Game.Genres != null)
{
foreach (long GenreId in Game.Genres.Ids)
{
Genre GameGenre = Genres.GetGenres(GenreId);
}
}
if (Game.InvolvedCompanies != null)
{
foreach (long involvedCompanyId in Game.InvolvedCompanies.Ids)
@@ -212,22 +247,6 @@ namespace gaseous_server.Classes.Metadata
}
}
if (Game.GameModes != null)
{
foreach (long gameModeId in Game.GameModes.Ids)
{
GameMode gameMode = GameModes.GetGame_Modes(gameModeId);
}
}
if (Game.MultiplayerModes != null)
{
foreach (long multiplayerModeId in Game.MultiplayerModes.Ids)
{
MultiplayerMode multiplayerMode = MultiplayerModes.GetGame_MultiplayerModes(multiplayerModeId);
}
}
if (Game.Platforms != null)
{
foreach (long PlatformId in Game.Platforms.Ids)
@@ -236,14 +255,6 @@ namespace gaseous_server.Classes.Metadata
}
}
if (Game.PlayerPerspectives != null)
{
foreach (long PerspectiveId in Game.PlayerPerspectives.Ids)
{
PlayerPerspective GamePlayPerspective = PlayerPerspectives.GetGame_PlayerPerspectives(PerspectiveId);
}
}
if (Game.Screenshots != null)
{
foreach (long ScreenshotId in Game.Screenshots.Ids)
@@ -252,14 +263,6 @@ namespace gaseous_server.Classes.Metadata
}
}
if (Game.Themes != null)
{
foreach (long ThemeId in Game.Themes.Ids)
{
Theme GameTheme = Themes.GetGame_Themes(ThemeId);
}
}
if (Game.Videos != null)
{
foreach (long GameVideoId in Game.Videos.Ids)

View File

@@ -2,7 +2,6 @@
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata

View File

@@ -2,7 +2,6 @@
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata

View File

@@ -2,7 +2,6 @@
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata

View File

@@ -2,7 +2,6 @@
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata

View File

@@ -2,7 +2,6 @@
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata

View File

@@ -153,6 +153,9 @@ namespace gaseous_server.Classes.Metadata
newDict = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(newObjectValue);
newObjectValue = Newtonsoft.Json.JsonConvert.SerializeObject(newDict["Ids"]);
objectDict[key.Key] = newObjectValue;
StoreRelations(ObjectTypeName, key.Key, (long)objectDict["Id"], newObjectValue);
break;
case "int32[]":
newObjectValue = Newtonsoft.Json.JsonConvert.SerializeObject(objectValue);
@@ -419,6 +422,39 @@ namespace gaseous_server.Classes.Metadata
return EndpointType;
}
private static void StoreRelations(string PrimaryTable, string SecondaryTable, long ObjectId, string Relations)
{
string TableName = "Relation_" + PrimaryTable + "_" + SecondaryTable;
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "SELECT * FROM information_schema.tables WHERE table_schema = '" + Config.DatabaseConfiguration.DatabaseName + "' AND table_name = '" + TableName + "';";
DataTable data = db.ExecuteCMD(sql);
if (data.Rows.Count == 0)
{
// table doesn't exist, create it
sql = "CREATE TABLE `" + Config.DatabaseConfiguration.DatabaseName + "`.`" + TableName + "` (`" + PrimaryTable + "Id` BIGINT NOT NULL, `" + SecondaryTable + "Id` BIGINT NOT NULL, PRIMARY KEY (`" + PrimaryTable + "Id`, `" + SecondaryTable + "Id`), INDEX `idx_PrimaryColumn` (`" + PrimaryTable + "Id` ASC) VISIBLE);";
db.ExecuteCMD(sql);
}
else
{
// clean existing records for this object
sql = "DELETE FROM " + TableName + " WHERE `" + PrimaryTable + "Id` = @objectid";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("objectid", ObjectId);
db.ExecuteCMD(sql, dbDict);
}
// insert data
long[] RelationValues = Newtonsoft.Json.JsonConvert.DeserializeObject<long[]>(Relations);
foreach (long RelationValue in RelationValues)
{
sql = "INSERT INTO " + TableName + " (`" + PrimaryTable + "Id`, `" + SecondaryTable + "Id`) VALUES (@objectid, @relationvalue);";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("objectid", ObjectId);
dbDict.Add("relationvalue", RelationValue);
db.ExecuteCMD(sql, dbDict);
}
}
private static void CacheClean()
{
if (ObjectCache == null)

View File

@@ -2,7 +2,6 @@
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata

View File

@@ -1,9 +1,7 @@
using System;
using System.IO;
using MySql.Data.MySqlClient;
using gaseous_signature_parser.models.RomSignatureObject;
using gaseous_tools;
using MySqlX.XDevAPI;
using System.Data;
namespace gaseous_server.SignatureIngestors.XML
@@ -62,6 +60,11 @@ namespace gaseous_server.SignatureIngestors.XML
{
sql = "SELECT * FROM Signatures_Sources WHERE SourceMD5=@sourcemd5";
dbDict = new Dictionary<string, object>();
string sourceUriStr = "";
if (Object.Url != null)
{
sourceUriStr = Object.Url.ToString();
}
dbDict.Add("name", Common.ReturnValueIfNull(Object.Name, ""));
dbDict.Add("description", Common.ReturnValueIfNull(Object.Description, ""));
dbDict.Add("category", Common.ReturnValueIfNull(Object.Category, ""));
@@ -69,7 +72,7 @@ namespace gaseous_server.SignatureIngestors.XML
dbDict.Add("author", Common.ReturnValueIfNull(Object.Author, ""));
dbDict.Add("email", Common.ReturnValueIfNull(Object.Email, ""));
dbDict.Add("homepage", Common.ReturnValueIfNull(Object.Homepage, ""));
dbDict.Add("uri", Common.ReturnValueIfNull(Object.Url, ""));
dbDict.Add("uri", sourceUriStr);
dbDict.Add("sourcetype", Common.ReturnValueIfNull(Object.SourceType, ""));
dbDict.Add("sourcemd5", Object.SourceMd5);
dbDict.Add("sourcesha1", Object.SourceSHA1);

View File

@@ -36,7 +36,7 @@ namespace gaseous_server.Controllers
// genres
List<Genre> genres = new List<Genre>();
sql = "SELECT DISTINCT t1.Id, t1.`Name` FROM Genre AS t1 JOIN (SELECT * FROM Game WHERE (SELECT COUNT(Id) FROM Games_Roms WHERE GameId = Game.Id) > 0) AS t2 ON JSON_CONTAINS(t2.Genres, CAST(t1.Id AS char), '$') ORDER BY t1.`Name`";
sql = "SELECT DISTINCT Relation_Game_Genres.GenresId AS id, Genre.`Name` FROM Relation_Game_Genres JOIN Genre ON Relation_Game_Genres.GenresId = Genre.Id WHERE Relation_Game_Genres.GameId IN (SELECT DISTINCT GameId FROM Games_Roms) ORDER BY `Name`;";
dbResponse = db.ExecuteCMD(sql);
foreach (DataRow dr in dbResponse.Rows)
@@ -47,7 +47,7 @@ namespace gaseous_server.Controllers
// game modes
List<GameMode> gameModes = new List<GameMode>();
sql = "SELECT DISTINCT t1.Id, t1.`Name` FROM GameMode AS t1 JOIN (SELECT * FROM Game WHERE (SELECT COUNT(Id) FROM Games_Roms WHERE GameId = Game.Id) > 0) AS t2 ON JSON_CONTAINS(t2.GameModes, CAST(t1.Id AS char), '$') ORDER BY t1.Id";
sql = "SELECT DISTINCT Relation_Game_GameModes.GameModesId AS id, GameMode.`Name` FROM Relation_Game_GameModes JOIN GameMode ON Relation_Game_GameModes.GameModesId = GameMode.Id WHERE Relation_Game_GameModes.GameId IN (SELECT DISTINCT GameId FROM Games_Roms) ORDER BY `Name`;";
dbResponse = db.ExecuteCMD(sql);
foreach (DataRow dr in dbResponse.Rows)
@@ -58,7 +58,7 @@ namespace gaseous_server.Controllers
// player perspectives
List<PlayerPerspective> playerPerspectives = new List<PlayerPerspective>();
sql = "SELECT DISTINCT t1.Id, t1.`Name` FROM PlayerPerspective AS t1 JOIN (SELECT * FROM Game WHERE (SELECT COUNT(Id) FROM Games_Roms WHERE GameId = Game.Id) > 0) AS t2 ON JSON_CONTAINS(t2.PlayerPerspectives, CAST(t1.Id AS char), '$') ORDER BY t1.`Name`";
sql = "SELECT DISTINCT Relation_Game_PlayerPerspectives.PlayerPerspectivesId AS id, PlayerPerspective.`Name` FROM Relation_Game_PlayerPerspectives JOIN PlayerPerspective ON Relation_Game_PlayerPerspectives.PlayerPerspectivesId = PlayerPerspective.Id WHERE Relation_Game_PlayerPerspectives.GameId IN (SELECT DISTINCT GameId FROM Games_Roms) ORDER BY `Name`;";
dbResponse = db.ExecuteCMD(sql);
foreach (DataRow dr in dbResponse.Rows)
@@ -69,7 +69,7 @@ namespace gaseous_server.Controllers
// themes
List<Theme> themes = new List<Theme>();
sql = "SELECT DISTINCT t1.Id, t1.`Name` FROM Theme AS t1 JOIN (SELECT * FROM Game WHERE (SELECT COUNT(Id) FROM Games_Roms WHERE GameId = Game.Id) > 0) AS t2 ON JSON_CONTAINS(t2.Themes, CAST(t1.Id AS char), '$') ORDER BY t1.`Name`";
sql = "SELECT DISTINCT Relation_Game_Themes.ThemesId AS id, Theme.`Name` FROM Relation_Game_Themes JOIN Theme ON Relation_Game_Themes.ThemesId = Theme.Id WHERE Relation_Game_Themes.GameId IN (SELECT DISTINCT GameId FROM Games_Roms) ORDER BY `Name`;";
dbResponse = db.ExecuteCMD(sql);
foreach (DataRow dr in dbResponse.Rows)

View File

@@ -12,7 +12,6 @@ using IGDB.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.CodeAnalysis.Scripting;
using Org.BouncyCastle.Asn1.X509;
using static gaseous_server.Classes.Metadata.AgeRatings;
namespace gaseous_server.Controllers
@@ -99,7 +98,7 @@ namespace gaseous_server.Controllers
if (genre.Length > 0)
{
tempVal = "(";
tempVal = "Relation_Game_Genres.GenresId IN (";
string[] genreClauseItems = genre.Split(",");
for (int i = 0; i < genreClauseItems.Length; i++)
{
@@ -108,7 +107,7 @@ namespace gaseous_server.Controllers
tempVal += " AND ";
}
string genreLabel = "@Genre" + i;
tempVal += "JSON_CONTAINS(Game.Genres, " + genreLabel + ", '$')";
tempVal += genreLabel;
whereParams.Add(genreLabel, genreClauseItems[i]);
}
tempVal += ")";
@@ -117,7 +116,7 @@ namespace gaseous_server.Controllers
if (gamemode.Length > 0)
{
tempVal = "(";
tempVal = "Relation_Game_GameModes.GameModesId IN (";
string[] gameModeClauseItems = gamemode.Split(",");
for (int i = 0; i < gameModeClauseItems.Length; i++)
{
@@ -126,7 +125,7 @@ namespace gaseous_server.Controllers
tempVal += " AND ";
}
string gameModeLabel = "@GameMode" + i;
tempVal += "JSON_CONTAINS(Game.GameModes, " + gameModeLabel + ", '$')";
tempVal += gameModeLabel;
whereParams.Add(gameModeLabel, gameModeClauseItems[i]);
}
tempVal += ")";
@@ -135,7 +134,7 @@ namespace gaseous_server.Controllers
if (playerperspective.Length > 0)
{
tempVal = "(";
tempVal = "Relation_Game_PlayerPerspectives.PlayerPerspectivesId IN (";
string[] playerPerspectiveClauseItems = playerperspective.Split(",");
for (int i = 0; i < playerPerspectiveClauseItems.Length; i++)
{
@@ -144,7 +143,7 @@ namespace gaseous_server.Controllers
tempVal += " AND ";
}
string playerPerspectiveLabel = "@PlayerPerspective" + i;
tempVal += "JSON_CONTAINS(Game.PlayerPerspectives, " + playerPerspectiveLabel + ", '$')";
tempVal += playerPerspectiveLabel;
whereParams.Add(playerPerspectiveLabel, playerPerspectiveClauseItems[i]);
}
tempVal += ")";
@@ -153,7 +152,7 @@ namespace gaseous_server.Controllers
if (theme.Length > 0)
{
tempVal = "(";
tempVal = "Relation_Game_Themes.ThemesId IN (";
string[] themeClauseItems = theme.Split(",");
for (int i = 0; i < themeClauseItems.Length; i++)
{
@@ -162,7 +161,7 @@ namespace gaseous_server.Controllers
tempVal += " AND ";
}
string themeLabel = "@Theme" + i;
tempVal += "JSON_CONTAINS(Game.Themes, " + themeLabel + ", '$')";
tempVal += themeLabel;
whereParams.Add(themeLabel, themeClauseItems[i]);
}
tempVal += ")";
@@ -205,7 +204,7 @@ namespace gaseous_server.Controllers
}
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "SELECT DISTINCT Games_Roms.GameId AS ROMGameId, Game.Id, Game.AgeRatings, Game.AggregatedRating, Game.AggregatedRatingCount, Game.AlternativeNames, Game.Artworks, Game.Bundles, Game.Category, Game.Collection, Game.Cover, Game.Dlcs, Game.Expansions, Game.ExternalGames, Game.FirstReleaseDate, Game.`Follows`, Game.Franchise, Game.Franchises, Game.GameEngines, Game.GameModes, Game.Genres, Game.Hypes, Game.InvolvedCompanies, Game.Keywords, Game.MultiplayerModes, Game.`Name`, Game.ParentGame, Game.Platforms, Game.PlayerPerspectives, Game.Rating, Game.RatingCount, Game.ReleaseDates, Game.Screenshots, Game.SimilarGames, Game.Slug, Game.StandaloneExpansions, Game.`Status`, Game.StoryLine, Game.Summary, Game.Tags, Game.Themes, Game.TotalRating, Game.TotalRatingCount, Game.VersionParent, Game.VersionTitle, Game.Videos, Game.Websites FROM gaseous.Games_Roms LEFT JOIN Game ON Game.Id = Games_Roms.GameId " + whereClause + " " + havingClause + " " + orderByClause;
string sql = "SELECT DISTINCT Games_Roms.GameId AS ROMGameId, Game.* FROM Games_Roms LEFT JOIN Game ON Game.Id = Games_Roms.GameId LEFT JOIN Relation_Game_Genres ON Game.Id = Relation_Game_Genres.GameId LEFT JOIN Relation_Game_GameModes ON Game.Id = Relation_Game_GameModes.GameId LEFT JOIN Relation_Game_PlayerPerspectives ON Game.Id = Relation_Game_PlayerPerspectives.GameId LEFT JOIN Relation_Game_Themes ON Game.Id = Relation_Game_Themes.GameId " + whereClause + " " + havingClause + " " + orderByClause;
List<IGDB.Models.Game> RetVal = new List<IGDB.Models.Game>();

View File

@@ -30,7 +30,7 @@ namespace gaseous_server.Controllers
{
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "SELECT * FROM gaseous.Platform WHERE Id IN (SELECT DISTINCT PlatformId FROM Games_Roms) ORDER BY `Name` ASC;";
string sql = "SELECT * FROM Platform WHERE Id IN (SELECT DISTINCT PlatformId FROM Games_Roms) ORDER BY `Name` ASC;";
List<Platform> RetVal = new List<Platform>();

View File

@@ -12,7 +12,6 @@ using IGDB.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.CodeAnalysis.Scripting;
using Org.BouncyCastle.Asn1.X509;
using static gaseous_server.Classes.Metadata.AgeRatings;
namespace gaseous_server.Controllers

View File

@@ -72,6 +72,9 @@ namespace gaseous_server.Models
foreach (PlatformMapItem mapItem in platforms)
{
// get the IGDB platform data
Platform platform = Platforms.GetPlatform(mapItem.IGDBId);
try
{
PlatformMapItem item = GetPlatformMap(mapItem.IGDBId);

View File

@@ -12,7 +12,7 @@ using Microsoft.OpenApi.Models;
Logging.WriteToDiskOnly = true;
Logging.Log(Logging.LogType.Information, "Startup", "Starting Gaseous Server " + Assembly.GetExecutingAssembly().GetName().Version);
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionStringNoDatabase);
// check db availability
bool dbOnline = false;
@@ -27,7 +27,9 @@ do
{
Thread.Sleep(30000);
}
} while (dbOnline == true);
} while (dbOnline == false);
db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
// set up db
db.InitDB();

View File

@@ -1,6 +1,5 @@
using System;
using System.Data;
using Google.Protobuf.WellKnownTypes;
using Newtonsoft.Json;
using IGDB.Models;
@@ -313,6 +312,16 @@ namespace gaseous_tools
return dbConnString;
}
}
[JsonIgnore]
public string ConnectionStringNoDatabase
{
get
{
string dbConnString = "server=" + HostName + ";port=" + Port + ";userid=" + UserName + ";password=" + Password + ";";
return dbConnString;
}
}
}
public class Library

View File

@@ -3,7 +3,7 @@ using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Reflection;
using MySql.Data.MySqlClient;
using MySqlConnector;
using static gaseous_tools.Database;
namespace gaseous_tools
@@ -69,7 +69,7 @@ namespace gaseous_tools
ExecuteCMD(sql, dbDict, 30, "server=" + Config.DatabaseConfiguration.HostName + ";port=" + Config.DatabaseConfiguration.Port + ";userid=" + Config.DatabaseConfiguration.UserName + ";password=" + Config.DatabaseConfiguration.Password);
// check if schema version table is in place - if not, create the schema version table
sql = "SELECT TABLE_SCHEMA, TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'gaseous' AND TABLE_NAME = 'schema_version';";
sql = "SELECT TABLE_SCHEMA, TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = '" + Config.DatabaseConfiguration.DatabaseName + "' AND TABLE_NAME = 'schema_version';";
DataTable SchemaVersionPresent = ExecuteCMD(sql, dbDict);
if (SchemaVersionPresent.Rows.Count == 0)
{

View File

@@ -3,7 +3,7 @@ CREATE TABLE `AgeRating` (
`Id` bigint NOT NULL,
`Category` int DEFAULT NULL,
`Checksum` varchar(45) DEFAULT NULL,
`ContentDescriptions` json DEFAULT NULL,
`ContentDescriptions` longtext DEFAULT NULL,
`Rating` int DEFAULT NULL,
`RatingCoverUrl` varchar(255) DEFAULT NULL,
`Synopsis` longtext,
@@ -55,7 +55,7 @@ DROP TABLE IF EXISTS `Collection`;
CREATE TABLE `Collection` (
`Id` bigint NOT NULL,
`Checksum` varchar(45) DEFAULT NULL,
`Games` json DEFAULT NULL,
`Games` longtext DEFAULT NULL,
`Name` varchar(255) DEFAULT NULL,
`Slug` varchar(100) DEFAULT NULL,
`CreatedAt` datetime DEFAULT NULL,
@@ -76,17 +76,17 @@ CREATE TABLE `Company` (
`Country` int DEFAULT NULL,
`CreatedAt` datetime DEFAULT NULL,
`Description` longtext,
`Developed` json DEFAULT NULL,
`Developed` longtext DEFAULT NULL,
`Logo` bigint DEFAULT NULL,
`Name` varchar(255) DEFAULT NULL,
`Parent` bigint DEFAULT NULL,
`Published` json DEFAULT NULL,
`Published` longtext DEFAULT NULL,
`Slug` varchar(100) DEFAULT NULL,
`StartDate` datetime DEFAULT NULL,
`StartDateCategory` int DEFAULT NULL,
`UpdatedAt` datetime DEFAULT NULL,
`Url` varchar(255) DEFAULT NULL,
`Websites` json DEFAULT NULL,
`Websites` longtext DEFAULT NULL,
`dateAdded` datetime DEFAULT NULL,
`lastUpdated` datetime DEFAULT NULL,
PRIMARY KEY (`Id`)
@@ -129,7 +129,7 @@ CREATE TABLE `ExternalGame` (
`Category` int DEFAULT NULL,
`Checksum` varchar(45) DEFAULT NULL,
`CreatedAt` datetime DEFAULT NULL,
`Countries` json DEFAULT NULL,
`Countries` longtext DEFAULT NULL,
`Game` bigint DEFAULT NULL,
`Media` int DEFAULT NULL,
`Name` varchar(255) DEFAULT NULL,
@@ -149,7 +149,7 @@ CREATE TABLE `Franchise` (
`Checksum` varchar(45) DEFAULT NULL,
`CreatedAt` datetime DEFAULT NULL,
`UpdatedAt` datetime DEFAULT NULL,
`Games` json DEFAULT NULL,
`Games` longtext DEFAULT NULL,
`Name` varchar(255) DEFAULT NULL,
`Slug` varchar(255) DEFAULT NULL,
`Url` varchar(255) DEFAULT NULL,
@@ -161,83 +161,59 @@ CREATE TABLE `Franchise` (
DROP TABLE IF EXISTS `Game`;
CREATE TABLE `Game` (
`Id` bigint NOT NULL,
`AgeRatings` json DEFAULT NULL,
`AgeRatings` longtext DEFAULT NULL,
`AggregatedRating` double DEFAULT NULL,
`AggregatedRatingCount` int DEFAULT NULL,
`AlternativeNames` json DEFAULT NULL,
`Artworks` json DEFAULT NULL,
`Bundles` json DEFAULT NULL,
`AlternativeNames` longtext DEFAULT NULL,
`Artworks` longtext DEFAULT NULL,
`Bundles` longtext DEFAULT NULL,
`Category` int DEFAULT NULL,
`Checksum` varchar(45) DEFAULT NULL,
`Collection` bigint DEFAULT NULL,
`Cover` bigint DEFAULT NULL,
`CreatedAt` datetime DEFAULT NULL,
`Dlcs` json DEFAULT NULL,
`Expansions` json DEFAULT NULL,
`ExternalGames` json DEFAULT NULL,
`Dlcs` longtext DEFAULT NULL,
`Expansions` longtext DEFAULT NULL,
`ExternalGames` longtext DEFAULT NULL,
`FirstReleaseDate` datetime DEFAULT NULL,
`Follows` int DEFAULT NULL,
`Franchise` bigint DEFAULT NULL,
`Franchises` json DEFAULT NULL,
`GameEngines` json DEFAULT NULL,
`GameModes` json DEFAULT NULL,
`Genres` json DEFAULT NULL,
`Franchises` longtext DEFAULT NULL,
`GameEngines` longtext DEFAULT NULL,
`GameModes` longtext DEFAULT NULL,
`Genres` longtext DEFAULT NULL,
`Hypes` int DEFAULT NULL,
`InvolvedCompanies` json DEFAULT NULL,
`Keywords` json DEFAULT NULL,
`MultiplayerModes` json DEFAULT NULL,
`InvolvedCompanies` longtext DEFAULT NULL,
`Keywords` longtext DEFAULT NULL,
`MultiplayerModes` longtext DEFAULT NULL,
`Name` varchar(255) DEFAULT NULL,
`ParentGame` bigint DEFAULT NULL,
`Platforms` json DEFAULT NULL,
`PlayerPerspectives` json DEFAULT NULL,
`Platforms` longtext DEFAULT NULL,
`PlayerPerspectives` longtext DEFAULT NULL,
`Rating` double DEFAULT NULL,
`RatingCount` int DEFAULT NULL,
`ReleaseDates` json DEFAULT NULL,
`Screenshots` json DEFAULT NULL,
`SimilarGames` json DEFAULT NULL,
`ReleaseDates` longtext DEFAULT NULL,
`Screenshots` longtext DEFAULT NULL,
`SimilarGames` longtext DEFAULT NULL,
`Slug` varchar(100) DEFAULT NULL,
`StandaloneExpansions` json DEFAULT NULL,
`StandaloneExpansions` longtext DEFAULT NULL,
`Status` int DEFAULT NULL,
`StoryLine` longtext,
`Summary` longtext,
`Tags` json DEFAULT NULL,
`Themes` json DEFAULT NULL,
`Tags` longtext DEFAULT NULL,
`Themes` longtext DEFAULT NULL,
`TotalRating` double DEFAULT NULL,
`TotalRatingCount` int DEFAULT NULL,
`UpdatedAt` datetime DEFAULT NULL,
`Url` varchar(255) DEFAULT NULL,
`VersionParent` bigint DEFAULT NULL,
`VersionTitle` varchar(100) DEFAULT NULL,
`Videos` json DEFAULT NULL,
`Websites` json DEFAULT NULL,
`Videos` longtext DEFAULT NULL,
`Websites` longtext DEFAULT NULL,
`dateAdded` datetime DEFAULT NULL,
`lastUpdated` datetime DEFAULT NULL,
PRIMARY KEY (`Id`),
UNIQUE KEY `Id_UNIQUE` (`Id`),
KEY `Idx_AgeRatings` ((cast(`AgeRatings` as unsigned array))),
KEY `Idx_Genres` ((cast(`Genres` as unsigned array))),
KEY `Idx_alternativeNames` ((cast(`AlternativeNames` as unsigned array))),
KEY `Idx_artworks` ((cast(`Artworks` as unsigned array))),
KEY `Idx_bundles` ((cast(`Bundles` as unsigned array))),
KEY `Idx_dlcs` ((cast(`Dlcs` as unsigned array))),
KEY `Idx_expansions` ((cast(`Expansions` as unsigned array))),
KEY `Idx_ExternalGames` ((cast(`ExternalGames` as unsigned array))),
KEY `Idx_franchises` ((cast(`Franchises` as unsigned array))),
KEY `Idx_Gameengines` ((cast(`GameEngines` as unsigned array))),
KEY `Idx_Gamemodes` ((cast(`GameModes` as unsigned array))),
KEY `Idx_involvedcompanies` ((cast(`InvolvedCompanies` as unsigned array))),
KEY `Idx_keywords` ((cast(`Keywords` as unsigned array))),
KEY `Idx_multiplayermodes` ((cast(`MultiplayerModes` as unsigned array))),
KEY `Idx_Platforms` ((cast(`Platforms` as unsigned array))),
KEY `Idx_playerperspectives` ((cast(`PlayerPerspectives` as unsigned array))),
KEY `Idx_releasedates` ((cast(`ReleaseDates` as unsigned array))),
KEY `Idx_Screenshots` ((cast(`Screenshots` as unsigned array))),
KEY `Idx_similarGames` ((cast(`SimilarGames` as unsigned array))),
KEY `Idx_standaloneexpansions` ((cast(`StandaloneExpansions` as unsigned array))),
KEY `Idx_tags` ((cast(`Tags` as unsigned array))),
KEY `Idx_themes` ((cast(`Themes` as unsigned array))),
KEY `Idx_vIdeos` ((cast(`Videos` as unsigned array))),
KEY `Idx_websites` ((cast(`Websites` as unsigned array)))
UNIQUE KEY `Id_UNIQUE` (`Id`)
);
DROP TABLE IF EXISTS `Games_Roms`;
@@ -251,7 +227,7 @@ CREATE TABLE `Games_Roms` (
`MD5` varchar(100) DEFAULT NULL,
`SHA1` varchar(100) DEFAULT NULL,
`DevelopmentStatus` varchar(100) DEFAULT NULL,
`Flags` json DEFAULT NULL,
`Flags` longtext DEFAULT NULL,
`RomType` int DEFAULT NULL,
`RomTypeMedia` varchar(100) DEFAULT NULL,
`MediaLabel` varchar(100) DEFAULT NULL,
@@ -322,8 +298,8 @@ CREATE TABLE `Platform` (
`Summary` longtext,
`UpdatedAt` datetime DEFAULT NULL,
`Url` varchar(255) DEFAULT NULL,
`Versions` json DEFAULT NULL,
`Websites` json DEFAULT NULL,
`Versions` longtext DEFAULT NULL,
`Websites` longtext DEFAULT NULL,
`dateAdded` datetime DEFAULT NULL,
`lastUpdated` datetime DEFAULT NULL,
PRIMARY KEY (`Id`),
@@ -349,7 +325,7 @@ DROP TABLE IF EXISTS `PlatformVersion`;
CREATE TABLE `PlatformVersion` (
`Id` bigint NOT NULL,
`Checksum` varchar(45) DEFAULT NULL,
`Companies` json DEFAULT NULL,
`Companies` longtext DEFAULT NULL,
`Connectivity` longtext,
`CPU` longtext,
`Graphics` longtext,
@@ -360,7 +336,7 @@ CREATE TABLE `PlatformVersion` (
`OS` longtext,
`Output` longtext,
`PlatformLogo` int DEFAULT NULL,
`PlatformVersionReleaseDates` json DEFAULT NULL,
`PlatformVersionReleaseDates` longtext DEFAULT NULL,
`Resolutions` longtext,
`Slug` longtext,
`Sound` longtext,
@@ -445,7 +421,7 @@ CREATE TABLE `Signatures_Roms` (
`MD5` varchar(100) DEFAULT NULL,
`SHA1` varchar(100) DEFAULT NULL,
`DevelopmentStatus` varchar(100) DEFAULT NULL,
`Flags` json DEFAULT NULL,
`Flags` longtext DEFAULT NULL,
`RomType` int DEFAULT NULL,
`RomTypeMedia` varchar(100) DEFAULT NULL,
`MediaLabel` varchar(100) DEFAULT NULL,
@@ -454,8 +430,7 @@ CREATE TABLE `Signatures_Roms` (
UNIQUE KEY `Id_UNIQUE` (`Id`,`GameId`) USING BTREE,
KEY `GameId_Idx` (`GameId`),
KEY `md5_Idx` (`MD5`) USING BTREE,
KEY `sha1_Idx` (`SHA1`) USING BTREE,
KEY `flags_Idx` ((cast(`Flags` as char(255) array)))
KEY `sha1_Idx` (`SHA1`) USING BTREE
);
DROP TABLE IF EXISTS `Signatures_Sources`;

View File

@@ -69,11 +69,11 @@ CREATE TABLE `RomCollections` (
`Id` BIGINT NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(255) NULL,
`Description` LONGTEXT NULL,
`Platforms` JSON NULL,
`Genres` JSON NULL,
`Players` JSON NULL,
`PlayerPerspectives` JSON NULL,
`Themes` JSON NULL,
`Platforms` longtext NULL,
`Genres` longtext NULL,
`Players` longtext NULL,
`PlayerPerspectives` longtext NULL,
`Themes` longtext NULL,
`MinimumRating` INT NULL,
`MaximumRating` INT NULL,
`MaximumRomsPerPlatform` INT NULL,

View File

@@ -1,19 +1,16 @@
ALTER TABLE `Signatures_Roms`
DROP INDEX `flags_Idx`;
ALTER TABLE `Signatures_Roms`
ADD COLUMN `Attributes` JSON NULL AFTER `Flags`,
ADD COLUMN `Attributes` longtext NULL AFTER `Flags`,
ADD COLUMN `IngestorVersion` INT NULL DEFAULT 1;
ALTER TABLE `Games_Roms`
ADD COLUMN `Attributes` JSON NULL AFTER `Flags`,
ADD COLUMN `Attributes` longtext NULL AFTER `Flags`,
ADD COLUMN `MetadataGameName` VARCHAR(255) NULL AFTER `MetadataSource`,
ADD COLUMN `MetadataVersion` INT NULL DEFAULT 1;
ALTER TABLE `RomCollections`
ADD COLUMN `FolderStructure` INT NULL DEFAULT 0 AFTER `MaximumCollectionSizeInBytes`,
ADD COLUMN `IncludeBIOSFiles` BOOLEAN NULL DEFAULT 0 AFTER `FolderStructure`,
ADD COLUMN `AlwaysInclude` JSON NULL AFTER `IncludeBIOSFiles`;
ADD COLUMN `AlwaysInclude` longtext NULL AFTER `IncludeBIOSFiles`;
CREATE TABLE `PlatformMap` (
`Id` BIGINT NOT NULL,

View File

@@ -1,2 +1,2 @@
ALTER TABLE `PlatformMap`
ADD COLUMN `AvailableWebEmulators` JSON NULL;
ADD COLUMN `AvailableWebEmulators` longtext NULL;

View File

@@ -9,3 +9,31 @@ CREATE TABLE `GameLibraries` (
ALTER TABLE `Games_Roms`
ADD COLUMN `LibraryId` INT NULL DEFAULT 0 AFTER `MetadataVersion`;
CREATE TABLE `Relation_Game_Genres` (
`GameId` BIGINT NOT NULL,
`GenresId` BIGINT NOT NULL,
PRIMARY KEY (`GameId`, `GenresId`),
INDEX `idx_PrimaryColumn` (`GameId` ASC) VISIBLE
);
CREATE TABLE `Relation_Game_GameModes` (
`GameId` BIGINT NOT NULL,
`GameModesId` BIGINT NOT NULL,
PRIMARY KEY (`GameId`, `GameModesId`),
INDEX `idx_PrimaryColumn` (`GameId` ASC) VISIBLE
);
CREATE TABLE `Relation_Game_PlayerPerspectives` (
`GameId` BIGINT NOT NULL,
`PlayerPerspectivesId` BIGINT NOT NULL,
PRIMARY KEY (`GameId`, `PlayerPerspectivesId`),
INDEX `idx_PrimaryColumn` (`GameId` ASC) VISIBLE
);
CREATE TABLE `Relation_Game_Themes` (
`GameId` BIGINT NOT NULL,
`ThemesId` BIGINT NOT NULL,
PRIMARY KEY (`GameId`, `ThemesId`),
INDEX `idx_PrimaryColumn` (`GameId` ASC) VISIBLE
);

View File

@@ -3,7 +3,6 @@ using System.Data;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Metadata.Ecma335;
using Org.BouncyCastle.Utilities;
namespace gaseous_tools
{
public class Logging

View File

@@ -9,7 +9,7 @@
<ItemGroup>
<PackageReference Include="gaseous.IGDB" Version="1.0.1" />
<PackageReference Include="MySql.Data" Version="8.1.0" />
<PackageReference Include="MySqlConnector" Version="2.2.7" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>