mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-07-16 17:47:22 +00:00
Add user and brewery address tables
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
* enriched data, and complete generation results.
|
||||
*/
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "data_model/models.h"
|
||||
@@ -92,22 +93,40 @@ struct EnrichedCity {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A brewery's street-level address, distinct from the shared `City`
|
||||
* it belongs to. Mirrors the backend's `BreweryPostLocation` shape.
|
||||
* @brief A brewery's address. Owns the `City` it belongs to alongside its
|
||||
* street-level fields. Mirrors the `brewery_addresses` table and the
|
||||
* backend's `BreweryPostLocation` shape.
|
||||
*
|
||||
* Only `postal_code` is populated today -- street-address generation has no
|
||||
* fixture data or service yet.
|
||||
* Only `city` and `postal_code` are populated today -- street-address
|
||||
* generation has no fixture data or service yet, so the address lines stay
|
||||
* empty.
|
||||
*/
|
||||
struct Address {
|
||||
struct BreweryAddress {
|
||||
City city{};
|
||||
std::optional<std::string> address_line_1{};
|
||||
std::optional<std::string> address_line_2{};
|
||||
std::string postal_code{};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A user's address. Owns the `City` it belongs to alongside its
|
||||
* street-level fields. Mirrors the `user_addresses` table.
|
||||
*
|
||||
* Only `city` is populated today; the street-level columns exist for future
|
||||
* enrichment.
|
||||
*/
|
||||
struct UserAddress {
|
||||
City city{};
|
||||
std::optional<std::string> address_line_1{};
|
||||
std::optional<std::string> address_line_2{};
|
||||
std::optional<std::string> postal_code{};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Helper struct to store generated brewery data.
|
||||
*/
|
||||
struct BreweryRecord {
|
||||
City location;
|
||||
Address address;
|
||||
BreweryAddress address;
|
||||
BreweryResult brewery;
|
||||
};
|
||||
|
||||
@@ -119,7 +138,7 @@ struct BreweryRecord {
|
||||
* consumer can register real accounts from the pipeline's SQLite export.
|
||||
*/
|
||||
struct UserRecord {
|
||||
City location;
|
||||
UserAddress address{};
|
||||
UserResult user;
|
||||
std::string email{};
|
||||
std::string date_of_birth{};
|
||||
|
||||
@@ -60,16 +60,6 @@ struct City {
|
||||
* @brief Local language codes in priority order.
|
||||
*/
|
||||
std::vector<std::string> local_languages{};
|
||||
|
||||
/**
|
||||
* @brief Latitude in decimal degrees.
|
||||
*/
|
||||
double latitude{};
|
||||
|
||||
/**
|
||||
* @brief Longitude in decimal degrees.
|
||||
*/
|
||||
double longitude{};
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
|
||||
@@ -63,7 +63,9 @@ class SqliteExportService final : public IExportService {
|
||||
SqliteDatabaseHandle db_handle_;
|
||||
SqliteStatementHandle insert_city_stmt_;
|
||||
SqliteStatementHandle insert_brewery_stmt_;
|
||||
SqliteStatementHandle insert_brewery_address_stmt_;
|
||||
SqliteStatementHandle insert_user_stmt_;
|
||||
SqliteStatementHandle insert_user_address_stmt_;
|
||||
bool transaction_open_ = false;
|
||||
std::unordered_map<std::string, sqlite3_int64> city_cache_;
|
||||
};
|
||||
|
||||
@@ -27,9 +27,7 @@ CREATE TABLE IF NOT EXISTS cities (
|
||||
country TEXT NOT NULL,
|
||||
iso3166_1 TEXT NOT NULL,
|
||||
local_languages_json TEXT NOT NULL,
|
||||
latitude REAL NOT NULL,
|
||||
longitude REAL NOT NULL,
|
||||
UNIQUE(city, state_province, iso3166_2, country, latitude, longitude)
|
||||
UNIQUE(city, state_province, iso3166_2, country)
|
||||
);
|
||||
|
||||
)sql";
|
||||
@@ -43,19 +41,16 @@ CREATE TABLE IF NOT EXISTS breweries (
|
||||
description_en TEXT NOT NULL,
|
||||
name_local TEXT NOT NULL,
|
||||
description_local TEXT NOT NULL,
|
||||
postal_code TEXT NOT NULL,
|
||||
FOREIGN KEY(city_id) REFERENCES cities(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_breweries_city_id ON breweries(city_id);
|
||||
|
||||
)sql";
|
||||
|
||||
inline constexpr std::string_view kCreateUsersTableSql = R"sql(
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
city_id INTEGER NOT NULL,
|
||||
first_name TEXT NOT NULL,
|
||||
last_name TEXT NOT NULL,
|
||||
gender TEXT NOT NULL,
|
||||
@@ -63,12 +58,45 @@ CREATE TABLE IF NOT EXISTS users (
|
||||
bio TEXT NOT NULL,
|
||||
activity_weight REAL NOT NULL,
|
||||
email TEXT NOT NULL UNIQUE,
|
||||
date_of_birth TEXT NOT NULL,
|
||||
date_of_birth TEXT NOT NULL
|
||||
);
|
||||
|
||||
)sql";
|
||||
|
||||
inline constexpr std::string_view kCreateBreweryAddressTableSql = R"sql(
|
||||
CREATE TABLE IF NOT EXISTS brewery_addresses (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
brewery_id INTEGER NOT NULL,
|
||||
address_line_1 TEXT,
|
||||
address_line_2 TEXT,
|
||||
postal_code TEXT NOT NULL,
|
||||
city_id INTEGER NOT NULL,
|
||||
FOREIGN KEY(brewery_id) REFERENCES breweries(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(city_id) REFERENCES cities(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_users_city_id ON users(city_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_brewery_addresses_brewery_id
|
||||
ON brewery_addresses(brewery_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_brewery_addresses_city_id
|
||||
ON brewery_addresses(city_id);
|
||||
)sql";
|
||||
|
||||
inline constexpr std::string_view kCreateUserAddressTableSql = R"sql(
|
||||
CREATE TABLE IF NOT EXISTS user_addresses (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL,
|
||||
address_line_1 TEXT,
|
||||
address_line_2 TEXT,
|
||||
postal_code TEXT,
|
||||
city_id INTEGER NOT NULL,
|
||||
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(city_id) REFERENCES cities(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_user_addresses_user_id
|
||||
ON user_addresses(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_addresses_city_id
|
||||
ON user_addresses(city_id);
|
||||
)sql";
|
||||
|
||||
inline constexpr std::string_view kInsertCitySql = R"sql(
|
||||
@@ -78,10 +106,8 @@ INSERT INTO cities (
|
||||
iso3166_2,
|
||||
country,
|
||||
iso3166_1,
|
||||
local_languages_json,
|
||||
latitude,
|
||||
longitude
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?);
|
||||
local_languages_json
|
||||
) VALUES (?, ?, ?, ?, ?, ?);
|
||||
)sql";
|
||||
|
||||
inline constexpr std::string_view kInsertBrewerySql = R"sql(
|
||||
@@ -90,14 +116,12 @@ INSERT INTO breweries (
|
||||
name_en,
|
||||
description_en,
|
||||
name_local,
|
||||
description_local,
|
||||
postal_code
|
||||
) VALUES (?, ?, ?, ?, ?, ?);
|
||||
description_local
|
||||
) VALUES (?, ?, ?, ?, ?);
|
||||
)sql";
|
||||
|
||||
inline constexpr std::string_view kInsertUserSql = R"sql(
|
||||
INSERT INTO users (
|
||||
city_id,
|
||||
first_name,
|
||||
last_name,
|
||||
gender,
|
||||
@@ -106,7 +130,22 @@ INSERT INTO users (
|
||||
activity_weight,
|
||||
email,
|
||||
date_of_birth
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?);
|
||||
)sql";
|
||||
|
||||
inline constexpr std::string_view kInsertBreweryAddressSql = R"sql(
|
||||
INSERT INTO brewery_addresses (
|
||||
brewery_id,
|
||||
postal_code,
|
||||
city_id
|
||||
) VALUES (?, ?, ?);
|
||||
)sql";
|
||||
|
||||
inline constexpr std::string_view kInsertUserAddressSql = R"sql(
|
||||
INSERT INTO user_addresses (
|
||||
user_id,
|
||||
city_id
|
||||
) VALUES (?, ?);
|
||||
)sql";
|
||||
|
||||
// sqlite3_bind_*() parameter indices are 1-based, matching the "?"
|
||||
@@ -118,8 +157,6 @@ enum CityBindIndex {
|
||||
kCityCountryBindIndex,
|
||||
kCityIso31661BindIndex,
|
||||
kCityLanguagesBindIndex,
|
||||
kCityLatitudeBindIndex,
|
||||
kCityLongitudeBindIndex,
|
||||
};
|
||||
|
||||
enum BreweryBindIndex {
|
||||
@@ -128,12 +165,10 @@ enum BreweryBindIndex {
|
||||
kBreweryEnglishDescriptionBindIndex,
|
||||
kBreweryLocalNameBindIndex,
|
||||
kBreweryLocalDescriptionBindIndex,
|
||||
kBreweryPostalCodeBindIndex,
|
||||
};
|
||||
|
||||
enum UserBindIndex {
|
||||
kUserCityIdBindIndex = 1,
|
||||
kUserFirstNameBindIndex,
|
||||
kUserFirstNameBindIndex = 1,
|
||||
kUserLastNameBindIndex,
|
||||
kUserGenderBindIndex,
|
||||
kUserUsernameBindIndex,
|
||||
@@ -143,6 +178,17 @@ enum UserBindIndex {
|
||||
kUserDateOfBirthBindIndex,
|
||||
};
|
||||
|
||||
enum BreweryAddressBindIndex {
|
||||
kBreweryAddressBreweryIdBindIndex = 1,
|
||||
kBreweryAddressPostalCodeBindIndex,
|
||||
kBreweryAddressCityIdBindIndex,
|
||||
};
|
||||
|
||||
enum UserAddressBindIndex {
|
||||
kUserAddressUserIdBindIndex = 1,
|
||||
kUserAddressCityIdBindIndex,
|
||||
};
|
||||
|
||||
SqliteStatementHandle PrepareStatement(const SqliteDatabaseHandle& db_handle,
|
||||
std::string_view sql,
|
||||
const char* action);
|
||||
|
||||
Reference in New Issue
Block a user