1
0

init.sql 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. -- ---------------------------------------------------------
  2. -- Initial Database and User Setup (Run as MySQL Root)
  3. -- ---------------------------------------------------------
  4. CREATE DATABASE IF NOT EXISTS food_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  5. -- 1. Create the Owner User
  6. -- Has full rights and can grant privileges to others.
  7. CREATE USER IF NOT EXISTS 'db_owner'@'%' IDENTIFIED BY 'owner_pass';
  8. GRANT ALL PRIVILEGES ON food_db.* TO 'db_owner'@'%' WITH GRANT OPTION;
  9. -- 2. Create the Reader User
  10. -- Has only connect and read permissions.
  11. CREATE USER IF NOT EXISTS 'db_reader'@'%' IDENTIFIED BY 'reader_pass';
  12. GRANT USAGE ON *.* TO 'db_reader'@'%';
  13. -- 3. Create the Loader User
  14. -- Has connect and data manipulation permissions to load files.
  15. CREATE USER IF NOT EXISTS 'db_loader'@'%' IDENTIFIED BY 'loader_pass';
  16. GRANT USAGE ON *.* TO 'db_loader'@'%';
  17. GRANT FILE ON *.* TO 'db_loader'@'%'; -- Essential for LOAD DATA INFILE from any directory
  18. -- 4. Create the App Auth User
  19. -- Segregation of Duties: Handles only users table for web application routing.
  20. CREATE USER IF NOT EXISTS 'db_app_auth'@'%' IDENTIFIED BY 'app_auth_placeholder_pass';
  21. -- Note: Replace 'app_auth_placeholder_pass' later outside this script.
  22. GRANT USAGE ON *.* TO 'db_app_auth'@'%';
  23. FLUSH PRIVILEGES;
  24. -- ---------------------------------------------------------
  25. -- Table Creation & Grants (Logically executed by db_owner)
  26. -- ---------------------------------------------------------
  27. USE food_db;
  28. -- NOTE: The syntax you provided (`read_csv_auto`) is specific to DuckDB!
  29. -- MySQL does NOT support `read_csv_auto()` to dynamically create tables from CSV.
  30. -- In MySQL, you MUST define the table schema first, and then use LOAD DATA INFILE.
  31. -- Here is the MySQL equivalent process:
  32. -- Step A.1: Create Web Users Table
  33. CREATE TABLE IF NOT EXISTS users (
  34. id INT AUTO_INCREMENT PRIMARY KEY,
  35. username VARCHAR(100) UNIQUE NOT NULL,
  36. password_hash VARCHAR(255) NOT NULL,
  37. email VARCHAR(255),
  38. search_limit VARCHAR(50) DEFAULT '50',
  39. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  40. ) ENGINE=InnoDB;
  41. GRANT SELECT, INSERT, UPDATE ON food_db.users TO 'db_app_auth'@'%';
  42. -- Step A.2: Create Health Profiles Table
  43. CREATE TABLE IF NOT EXISTS user_health_profiles (
  44. id INT AUTO_INCREMENT PRIMARY KEY,
  45. user_id INT NOT NULL,
  46. illness_health_condition_diet_dislikes_name VARCHAR(100),
  47. illness_health_condition_diet_dislikes_value VARCHAR(255),
  48. FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
  49. ) ENGINE=InnoDB;
  50. GRANT SELECT, INSERT, UPDATE, DELETE ON food_db.user_health_profiles TO 'db_app_auth'@'%';
  51. -- Step A.3: Create Plate Builder Tables
  52. CREATE TABLE IF NOT EXISTS plates (
  53. id INT AUTO_INCREMENT PRIMARY KEY,
  54. user_id INT NOT NULL,
  55. plate_name VARCHAR(255) NOT NULL,
  56. FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
  57. ) ENGINE=InnoDB;
  58. CREATE TABLE IF NOT EXISTS plate_items (
  59. id INT AUTO_INCREMENT PRIMARY KEY,
  60. plate_id INT NOT NULL,
  61. product_code VARCHAR(50) NOT NULL,
  62. quantity_grams FLOAT NOT NULL,
  63. FOREIGN KEY (plate_id) REFERENCES plates(id) ON DELETE CASCADE
  64. ) ENGINE=InnoDB;
  65. GRANT SELECT, INSERT, UPDATE, DELETE ON food_db.plates TO 'db_app_auth'@'%';
  66. GRANT SELECT, INSERT, UPDATE, DELETE ON food_db.plate_items TO 'db_app_auth'@'%';
  67. FLUSH PRIVILEGES;
  68. -- Step A.2: Create the table with known columns (Example structure for OpenFoodFacts)
  69. CREATE TABLE IF NOT EXISTS products (
  70. code VARCHAR(50) PRIMARY KEY,
  71. url TEXT,
  72. creator VARCHAR(255),
  73. created_t VARCHAR(50),
  74. created_datetime VARCHAR(50),
  75. last_modified_t VARCHAR(50),
  76. last_modified_datetime VARCHAR(50),
  77. product_name TEXT,
  78. generic_name TEXT,
  79. quantity VARCHAR(255),
  80. packaging TEXT,
  81. brands TEXT,
  82. categories TEXT,
  83. origins TEXT,
  84. labels TEXT,
  85. stores TEXT,
  86. countries TEXT,
  87. ingredients_text TEXT,
  88. allergens TEXT,
  89. traces TEXT,
  90. -- Add FULLTEXT index for context search on ingredients and products
  91. FULLTEXT INDEX ft_idx_search (product_name, ingredients_text)
  92. ) ENGINE=InnoDB;
  93. CREATE TABLE IF NOT EXISTS products_core (
  94. code VARCHAR(50) PRIMARY KEY,
  95. product_name TEXT,
  96. generic_name TEXT,
  97. brands TEXT,
  98. ingredients_text TEXT,
  99. FULLTEXT INDEX ft_idx_search (product_name, ingredients_text),
  100. FULLTEXT INDEX ft_idx_pn (product_name),
  101. FULLTEXT INDEX ft_idx_it (ingredients_text)
  102. ) ENGINE=InnoDB;
  103. CREATE TABLE IF NOT EXISTS products_macros (
  104. code VARCHAR(50) PRIMARY KEY,
  105. `energy-kcal_100g` DOUBLE,
  106. proteins_100g DOUBLE,
  107. fat_100g DOUBLE,
  108. carbohydrates_100g DOUBLE,
  109. sugars_100g DOUBLE,
  110. fiber_100g DOUBLE,
  111. sodium_100g DOUBLE,
  112. salt_100g DOUBLE,
  113. cholesterol_100g DOUBLE
  114. ) ENGINE=InnoDB;
  115. CREATE TABLE IF NOT EXISTS products_vitamins (
  116. code VARCHAR(50) PRIMARY KEY,
  117. `vitamin-a_100g` DOUBLE,
  118. `vitamin-b1_100g` DOUBLE,
  119. `vitamin-b2_100g` DOUBLE,
  120. `vitamin-pp_100g` DOUBLE,
  121. `vitamin-b6_100g` DOUBLE,
  122. `vitamin-b9_100g` DOUBLE,
  123. `vitamin-b12_100g` DOUBLE,
  124. `vitamin-c_100g` DOUBLE,
  125. `vitamin-d_100g` DOUBLE,
  126. `vitamin-e_100g` DOUBLE,
  127. `vitamin-k_100g` DOUBLE
  128. ) ENGINE=InnoDB;
  129. CREATE TABLE IF NOT EXISTS products_minerals (
  130. code VARCHAR(50) PRIMARY KEY,
  131. calcium_100g DOUBLE,
  132. iron_100g DOUBLE,
  133. magnesium_100g DOUBLE,
  134. potassium_100g DOUBLE,
  135. zinc_100g DOUBLE
  136. ) ENGINE=InnoDB;
  137. CREATE TABLE IF NOT EXISTS products_allergens (
  138. code VARCHAR(50) PRIMARY KEY,
  139. allergens TEXT,
  140. traces TEXT
  141. ) ENGINE=InnoDB;
  142. -- Step B: The Owner grants explicit privileges to the Reader and Loader
  143. -- Grant explicit privileges to the Reader
  144. GRANT SELECT ON food_db.products TO 'db_reader'@'%';
  145. GRANT SELECT ON food_db.products_core TO 'db_reader'@'%';
  146. GRANT SELECT ON food_db.products_allergens TO 'db_reader'@'%';
  147. GRANT SELECT ON food_db.products_macros TO 'db_reader'@'%';
  148. GRANT SELECT ON food_db.products_vitamins TO 'db_reader'@'%';
  149. GRANT SELECT ON food_db.products_minerals TO 'db_reader'@'%';
  150. -- Grant broad privileges to the Loader on food_db to allow temp tables and UPSERT modifications
  151. GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE, ALTER, INDEX ON food_db.* TO 'db_loader'@'%';
  152. FLUSH PRIVILEGES;
  153. -- Step C: The Loader user would then run this MySQL command to import:
  154. /*
  155. LOAD DATA INFILE '/path/to/en.openfoodfacts.org.products.converted.csv'
  156. INTO TABLE products
  157. FIELDS TERMINATED BY '\t'
  158. ENCLOSED BY ''
  159. LINES TERMINATED BY '\n'
  160. IGNORE 1 ROWS;
  161. */