From 5b2eceb6b831e2f34e4eb77f024fc1c2f549529d Mon Sep 17 00:00:00 2001 From: Aaron Po Date: Mon, 20 Jul 2026 00:55:21 -0400 Subject: [PATCH] Add sqlite load into Database.Seed --- tooling/pipeline/CMakeLists.txt | 6 +- .../src/services/xeger/xeger_generator.cc | 10 +- .../Database.Seed/Database.Seed.csproj | 8 +- .../ConnectionStrings.cs} | 15 +- .../PipelineData/BreweryAddress.cs | 8 ++ .../PipelineData/BreweryRecord.cs | 8 ++ .../PipelineData/BreweryResult.cs | 12 ++ .../Database.Seed/PipelineData/City.cs | 18 +++ .../PipelineData/PostalCodeSpec.cs | 10 ++ .../Database.Seed/PipelineData/UserAddress.cs | 8 ++ .../Database.Seed/PipelineData/UserRecord.cs | 12 ++ .../Database.Seed/PipelineData/UserResult.cs | 16 +++ web/backend/Database/Database.Seed/Program.cs | 53 +++++++ .../Database.Seed/SeedData/seed.sqlite | Bin 0 -> 61440 bytes .../Sqlite/PipelineSeedDataReader.cs | 135 ++++++++++++++++++ 15 files changed, 298 insertions(+), 21 deletions(-) rename web/backend/Database/Database.Seed/{DatabaseHelpers.cs => DatabaseHelpers/ConnectionStrings.cs} (73%) create mode 100644 web/backend/Database/Database.Seed/PipelineData/BreweryAddress.cs create mode 100644 web/backend/Database/Database.Seed/PipelineData/BreweryRecord.cs create mode 100644 web/backend/Database/Database.Seed/PipelineData/BreweryResult.cs create mode 100644 web/backend/Database/Database.Seed/PipelineData/City.cs create mode 100644 web/backend/Database/Database.Seed/PipelineData/PostalCodeSpec.cs create mode 100644 web/backend/Database/Database.Seed/PipelineData/UserAddress.cs create mode 100644 web/backend/Database/Database.Seed/PipelineData/UserRecord.cs create mode 100644 web/backend/Database/Database.Seed/PipelineData/UserResult.cs create mode 100644 web/backend/Database/Database.Seed/Program.cs create mode 100644 web/backend/Database/Database.Seed/SeedData/seed.sqlite create mode 100644 web/backend/Database/Database.Seed/Sqlite/PipelineSeedDataReader.cs diff --git a/tooling/pipeline/CMakeLists.txt b/tooling/pipeline/CMakeLists.txt index 2716c490..220334bf 100644 --- a/tooling/pipeline/CMakeLists.txt +++ b/tooling/pipeline/CMakeLists.txt @@ -111,8 +111,9 @@ if(NOT BIERGARTEN_MOCK_ONLY) ) FetchContent_MakeAvailable(llama-cpp) endif() - + if (NOT APPLE) find_package(OpenMP REQUIRED) + endif() endif() # spdlog @@ -249,9 +250,10 @@ target_include_directories(${PROJECT_NAME} PRIVATE includes ) + target_link_libraries(${PROJECT_NAME} PRIVATE $<$>:llama> - $<$>:OpenMP::OpenMP_CXX> + $ boost::di Boost::json Boost::program_options diff --git a/tooling/pipeline/src/services/xeger/xeger_generator.cc b/tooling/pipeline/src/services/xeger/xeger_generator.cc index e812d898..82aca295 100644 --- a/tooling/pipeline/src/services/xeger/xeger_generator.cc +++ b/tooling/pipeline/src/services/xeger/xeger_generator.cc @@ -54,11 +54,11 @@ void XegerGenerator::Visit(const Alternation& node) { } void XegerGenerator::Visit(const Repeat& node) { - const int lo = node.min; - const int hi = (node.max < 0) ? node.min + unbounded_cap_ : node.max; - std::uniform_int_distribution dist(lo, hi); - const int count = dist(rng_); - for (int i = 0; i < count; ++i) { + const unsigned int low = node.min; + const unsigned int high = node.max.value_or(node.min + unbounded_cap_); + std::uniform_int_distribution dist(low, high); + const unsigned int count = dist(rng_); + for (unsigned int i = 0; i < count; ++i) { node.child->Accept(*this); } } diff --git a/web/backend/Database/Database.Seed/Database.Seed.csproj b/web/backend/Database/Database.Seed/Database.Seed.csproj index 0d9b350c..887c52c3 100644 --- a/web/backend/Database/Database.Seed/Database.Seed.csproj +++ b/web/backend/Database/Database.Seed/Database.Seed.csproj @@ -16,7 +16,7 @@ @@ -24,4 +24,10 @@ + + + + + diff --git a/web/backend/Database/Database.Seed/DatabaseHelpers.cs b/web/backend/Database/Database.Seed/DatabaseHelpers/ConnectionStrings.cs similarity index 73% rename from web/backend/Database/Database.Seed/DatabaseHelpers.cs rename to web/backend/Database/Database.Seed/DatabaseHelpers/ConnectionStrings.cs index 574296b4..6554b980 100644 --- a/web/backend/Database/Database.Seed/DatabaseHelpers.cs +++ b/web/backend/Database/Database.Seed/DatabaseHelpers/ConnectionStrings.cs @@ -1,19 +1,9 @@ using Microsoft.Data.SqlClient; -namespace Database.Seed; +namespace Database.Seed.DatabaseHelpers; public class ConnectionStrings { - /// - /// Builds a SQL Server connection string from the DB_SERVER, DB_NAME, - /// DB_USER, DB_PASSWORD, and DB_TRUST_SERVER_CERTIFICATE - /// environment variables. - /// - /// A fully built SQL Server connection string. - /// - /// Thrown when DB_SERVER, DB_NAME, DB_USER, or DB_PASSWORD - /// is not set. - /// private static string GetSqlServerConnectionString() { string server = @@ -48,7 +38,6 @@ public class ConnectionStrings return builder.ConnectionString; } - public static string SqlServerConnectionString => GetSqlServerConnectionString(); - public static string SqliteConnectionString => "Data Source=seed.sqlite"; + public static string SqliteConnectionString => "Data Source=SeedData/seed.sqlite"; } diff --git a/web/backend/Database/Database.Seed/PipelineData/BreweryAddress.cs b/web/backend/Database/Database.Seed/PipelineData/BreweryAddress.cs new file mode 100644 index 00000000..b6902bb1 --- /dev/null +++ b/web/backend/Database/Database.Seed/PipelineData/BreweryAddress.cs @@ -0,0 +1,8 @@ +namespace Database.Seed.PipelineData; + +public sealed record BreweryAddress +{ + public required City City { get; init; } + + public required string PostalCode { get; init; } +} diff --git a/web/backend/Database/Database.Seed/PipelineData/BreweryRecord.cs b/web/backend/Database/Database.Seed/PipelineData/BreweryRecord.cs new file mode 100644 index 00000000..93c67e9a --- /dev/null +++ b/web/backend/Database/Database.Seed/PipelineData/BreweryRecord.cs @@ -0,0 +1,8 @@ +namespace Database.Seed.PipelineData; + +public sealed record BreweryRecord +{ + public required BreweryAddress Address { get; init; } + + public required BreweryResult Brewery { get; init; } +} diff --git a/web/backend/Database/Database.Seed/PipelineData/BreweryResult.cs b/web/backend/Database/Database.Seed/PipelineData/BreweryResult.cs new file mode 100644 index 00000000..13d42f5f --- /dev/null +++ b/web/backend/Database/Database.Seed/PipelineData/BreweryResult.cs @@ -0,0 +1,12 @@ +namespace Database.Seed.PipelineData; + +public sealed record BreweryResult +{ + public required string NameEn { get; init; } + + public required string DescriptionEn { get; init; } + + public required string NameLocal { get; init; } + + public required string DescriptionLocal { get; init; } +} diff --git a/web/backend/Database/Database.Seed/PipelineData/City.cs b/web/backend/Database/Database.Seed/PipelineData/City.cs new file mode 100644 index 00000000..88de9e2e --- /dev/null +++ b/web/backend/Database/Database.Seed/PipelineData/City.cs @@ -0,0 +1,18 @@ +namespace Database.Seed.PipelineData; + +public sealed record City +{ + public required string CityName { get; init; } + + public required string StateProvince { get; init; } + + public required string Iso31662 { get; init; } + + public required string Country { get; init; } + + public required string Iso31661 { get; init; } + + public IReadOnlyList LocalLanguages { get; init; } = []; + + public required PostalCodeSpec PostalCode { get; init; } +} diff --git a/web/backend/Database/Database.Seed/PipelineData/PostalCodeSpec.cs b/web/backend/Database/Database.Seed/PipelineData/PostalCodeSpec.cs new file mode 100644 index 00000000..d367da6b --- /dev/null +++ b/web/backend/Database/Database.Seed/PipelineData/PostalCodeSpec.cs @@ -0,0 +1,10 @@ +namespace Database.Seed.PipelineData; + +public sealed record PostalCodeSpec +{ + public required string CountryFormatRegex { get; init; } + + public IReadOnlyList CityRegexes { get; init; } = []; + + public IReadOnlyList Examples { get; init; } = []; +} diff --git a/web/backend/Database/Database.Seed/PipelineData/UserAddress.cs b/web/backend/Database/Database.Seed/PipelineData/UserAddress.cs new file mode 100644 index 00000000..6b63a17c --- /dev/null +++ b/web/backend/Database/Database.Seed/PipelineData/UserAddress.cs @@ -0,0 +1,8 @@ +namespace Database.Seed.PipelineData; + +public sealed record UserAddress +{ + public required City City { get; init; } + + public required string PostalCode { get; init; } +} diff --git a/web/backend/Database/Database.Seed/PipelineData/UserRecord.cs b/web/backend/Database/Database.Seed/PipelineData/UserRecord.cs new file mode 100644 index 00000000..fa8f0dc2 --- /dev/null +++ b/web/backend/Database/Database.Seed/PipelineData/UserRecord.cs @@ -0,0 +1,12 @@ +namespace Database.Seed.PipelineData; + +public sealed record UserRecord +{ + public required UserAddress Address { get; init; } + + public required UserResult User { get; init; } + + public required string Email { get; init; } + + public required string DateOfBirth { get; init; } +} diff --git a/web/backend/Database/Database.Seed/PipelineData/UserResult.cs b/web/backend/Database/Database.Seed/PipelineData/UserResult.cs new file mode 100644 index 00000000..0e53881d --- /dev/null +++ b/web/backend/Database/Database.Seed/PipelineData/UserResult.cs @@ -0,0 +1,16 @@ +namespace Database.Seed.PipelineData; + +public sealed record UserResult +{ + public required string FirstName { get; init; } + + public required string LastName { get; init; } + + public required string Gender { get; init; } + + public required string Username { get; init; } + + public required string Bio { get; init; } + + public required float ActivityWeight { get; init; } +} diff --git a/web/backend/Database/Database.Seed/Program.cs b/web/backend/Database/Database.Seed/Program.cs new file mode 100644 index 00000000..6a025994 --- /dev/null +++ b/web/backend/Database/Database.Seed/Program.cs @@ -0,0 +1,53 @@ +using Database.Seed.DatabaseHelpers; +using Database.Seed.PipelineData; +using Database.Seed.Sqlite; +using Microsoft.Data.Sqlite; + +namespace Database.Seed; + +public class Program +{ + public static int Main() + { + IReadOnlyList breweries; + IReadOnlyList users; + try + { + PipelineSeedDataReader reader = new(ConnectionStrings.SqliteConnectionString); + breweries = reader.ReadBreweryRecords(); + users = reader.ReadUserRecords(); + } + catch (SqliteException ex) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine($"Error opening database connection: {ex.Message}"); + Console.ResetColor(); + return 1; + } + + + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine( + $"Loaded {breweries.Count} breweries." + ); + Console.ResetColor(); + + for (int i = 0; i < breweries.Count; i++) + { + BreweryRecord brewery = breweries[i]; + Console.WriteLine($"{i + 1}:\t{brewery.Brewery.NameEn}\t({brewery.Address.City.CityName}, {brewery.Address.City.Country})"); + } + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine($"Loaded {users.Count} users."); + Console.ResetColor(); + + for (int i = 0; i < users.Count; i++) + { + UserRecord user = users[i]; + Console.WriteLine($"{i + 1}:\t{user.User.FirstName} {user.User.LastName}\t ({user.Email})"); + } + + return 0; + + } +} diff --git a/web/backend/Database/Database.Seed/SeedData/seed.sqlite b/web/backend/Database/Database.Seed/SeedData/seed.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..06cd47a2ce47a2ab87dbcbc4d077327f667dd0f6 GIT binary patch literal 61440 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 F{{x*{4~hT) literal 0 HcmV?d00001 diff --git a/web/backend/Database/Database.Seed/Sqlite/PipelineSeedDataReader.cs b/web/backend/Database/Database.Seed/Sqlite/PipelineSeedDataReader.cs new file mode 100644 index 00000000..8657d121 --- /dev/null +++ b/web/backend/Database/Database.Seed/Sqlite/PipelineSeedDataReader.cs @@ -0,0 +1,135 @@ +using System.Text.Json; +using Database.Seed.PipelineData; +using Microsoft.Data.Sqlite; + +namespace Database.Seed.Sqlite; + +public sealed class PipelineSeedDataReader +{ + private readonly string _connectionString; + + public PipelineSeedDataReader(string connectionString) + { + _connectionString = connectionString; + } + + public IReadOnlyList ReadBreweryRecords() + { + using SqliteConnection connection = new(_connectionString); + connection.Open(); + + IReadOnlyDictionary cities = ReadCities(connection); + + const string sql = """ + SELECT b.name_en, b.description_en, b.name_local, b.description_local, + ba.city_id, ba.postal_code + FROM breweries b + JOIN brewery_addresses ba ON ba.brewery_id = b.id; + """; + + using SqliteCommand command = new(sql, connection); + using SqliteDataReader reader = command.ExecuteReader(); + + List records = []; + while (reader.Read()) + records.Add( + new BreweryRecord + { + Brewery = new BreweryResult + { + NameEn = reader.GetString(0), + DescriptionEn = reader.GetString(1), + NameLocal = reader.GetString(2), + DescriptionLocal = reader.GetString(3), + }, + Address = new BreweryAddress + { + City = cities[reader.GetInt64(4)], + PostalCode = reader.GetString(5), + }, + } + ); + + return records; + } + + public IReadOnlyList ReadUserRecords() + { + using SqliteConnection connection = new(_connectionString); + connection.Open(); + + IReadOnlyDictionary cities = ReadCities(connection); + + const string sql = """ + SELECT u.first_name, u.last_name, u.gender, u.username, u.bio, + u.activity_weight, u.email, u.date_of_birth, + ua.city_id, ua.postal_code + FROM users u + JOIN user_addresses ua ON ua.user_id = u.id; + """; + + using SqliteCommand command = new(sql, connection); + using SqliteDataReader reader = command.ExecuteReader(); + + List records = []; + while (reader.Read()) + records.Add( + new UserRecord + { + User = new UserResult + { + FirstName = reader.GetString(0), + LastName = reader.GetString(1), + Gender = reader.GetString(2), + Username = reader.GetString(3), + Bio = reader.GetString(4), + ActivityWeight = (float)reader.GetDouble(5), + }, + Email = reader.GetString(6), + DateOfBirth = reader.GetString(7), + Address = new UserAddress + { + City = cities[reader.GetInt64(8)], + PostalCode = reader.GetString(9), + }, + } + ); + + return records; + } + + private static IReadOnlyDictionary ReadCities(SqliteConnection connection) + { + const string sql = """ + SELECT id, city, state_province, iso3166_2, country, iso3166_1, + local_languages_json, postal_code_country_format_regex, + postal_code_city_regex_json + FROM cities; + """; + + using SqliteCommand command = new(sql, connection); + using SqliteDataReader reader = command.ExecuteReader(); + + Dictionary cities = []; + while (reader.Read()) + cities[reader.GetInt64(0)] = new City + { + CityName = reader.GetString(1), + StateProvince = reader.GetString(2), + Iso31662 = reader.GetString(3), + Country = reader.GetString(4), + Iso31661 = reader.GetString(5), + LocalLanguages = DeserializeStringArray(reader.GetString(6)), + PostalCode = new PostalCodeSpec + { + CountryFormatRegex = reader.GetString(7), + CityRegexes = DeserializeStringArray(reader.GetString(8)), + }, + }; + + return cities; + } + + private static IReadOnlyList DeserializeStringArray(string json) => + JsonSerializer.Deserialize>(json) ?? []; +}