Skip to content

Commit 8232e86

Browse files
committed
Небольшие улучшения кода. Изменение API на PostgreSQL.
1 parent bc9ffd1 commit 8232e86

10 files changed

Lines changed: 129 additions & 170 deletions

File tree

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@
1313
###### You need to set environment variables into .env file like this
1414

1515
```
16-
DB_NAME=postgre
17-
SECRET_KEY=secret
18-
USER_NAME=postgre
16+
STORE_DB_NAME=store-db
17+
STORE_DB_PSWD=store-pswd
18+
STORE_DB_USER=store-user
19+
20+
BANK_DB_NAME=bank-db
21+
BANK_DB_PSWD=bank-store
22+
BANK_DB_USER=bank-user
1923
2024
DB_PORT=51488
2125
```

database/init-scripts/15-store-init.sql

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,13 @@ COPY games(id, name, price, description, brief, studio_id)
1414
FROM '/store-init-csvs/init-data-games.csv'
1515
WITH (FORMAT CSV, HEADER, DELIMITER ',');
1616

17-
-- generator can generate duplicates for this categories
18-
-- COPY game_tags(game_id, tag_id)
19-
-- FROM '/store-init-csvs/init-data-game-tags.csv'
20-
-- WITH (FORMAT CSV, HEADER, DELIMITER ',');
17+
COPY game_tags(game_id, tag_id)
18+
FROM '/store-init-csvs/init-data-game-tags.csv'
19+
WITH (FORMAT CSV, HEADER, DELIMITER ',');
2120

22-
-- COPY purchases(id, owner_id, buyer_id, ts, game_id)
23-
-- FROM '/store-init-csvs/init-data-purchases.csv'
24-
-- WITH (FORMAT CSV, HEADER, DELIMITER ',', NULL 'NULL');
21+
COPY purchases(id, owner_id, buyer_id, ts, game_id)
22+
FROM '/store-init-csvs/init-data-purchases.csv'
23+
WITH (FORMAT CSV, HEADER, DELIMITER ',', NULL 'NULL');
2524

2625
-- create temporary table for games pictures to transform csv
2726
CREATE TEMP TABLE temp4gpictures (

docker-compose.yaml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ services:
66
env_file: .env
77
container_name: gamehub-db
88
environment:
9-
POSTGRES_USER: ${DB_USER}
10-
POSTGRES_PASSWORD: ${SECRET_KEY}
11-
POSTGRES_DB: ${DB_NAME}
9+
POSTGRES_USER: ${STORE_DB_USER}
10+
POSTGRES_PASSWORD: ${STORE_DB_PSWD}
11+
POSTGRES_DB: ${STORE_DB_NAME}
1212
PGPORT: ${DB_PORT}
1313
expose:
1414
- "${DB_PORT}"
@@ -31,6 +31,11 @@ services:
3131
- db
3232
environment:
3333
BANK_SERVICE_URL: http://bank-service:5001
34+
DB_HOST: db
35+
DB_PORT: ${DB_PORT}
36+
DB_NAME: ${STORE_DB_NAME}
37+
DB_USER: ${STORE_DB_USER}
38+
DB_PSWD: ${STORE_DB_PSWD}
3439
volumes:
3540
- ./database/store-init-csvs:/tmp/init-csvs/
3641
networks:

store-service/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ flask
22
uwsgi
33
bleach
44
pillow
5-
psycopg
5+
psycopg[binary,pool]
Lines changed: 53 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import sqlite3
1+
import psycopg
22
import os
33
import csv
44
import base64
@@ -9,71 +9,42 @@
99

1010
from store.utility.User import User
1111

12-
DB_PATH = os.environ.get('DB_PATH', '/var/store-db/store.sql3.db')
1312
INIT_CSV_PATH = os.environ.get('INIT_CSV_PATH', '/tmp/init-csvs')
1413
STATIC_PATH = os.environ.get('STATIC_PATH', '/store/store/static')
1514

16-
def init_pics_from_csv(db_file:str, csv_file:str, table_name:str, save_to:str):
17-
conn = sqlite3.connect(db_file)
18-
cursor = conn.cursor()
15+
def init_pics_from_csv(csv_file:str, table_name:str, save_to:str):
1916
try:
2017
with open(csv_file, 'r', encoding='UTF-8') as file:
2118
reader = csv.reader(file)
2219
headers = next(reader)[:-1]
23-
query = f"""
24-
INSERT OR IGNORE INTO {table_name} ({','.join(headers)})
25-
VALUES ({','.join(['?'] * len(headers))});
26-
"""
20+
2721
for row in reader:
2822
if save_to == 'profiles':
29-
img, data, path = base64.b64decode(row[-1]), row[:-1], f'{row[0]}.png'
23+
img, data, path = base64.b64decode(row[-1]), row[:-1], f'{row[0]}p.png'
3024
img = Image.open(io.BytesIO(img))
3125
img.save(f'{STATIC_PATH}/images/{save_to}/{path}')
3226
else :
3327
img, data = base64.b64decode(row[-1]), row[:-1]
3428
img = Image.open(io.BytesIO(img))
35-
game_id, path = data[2], data[1]
29+
game_id, path = data[2], f'{row[0]}g.{row[-2]}'
3630
os.makedirs(f'{STATIC_PATH}/images/{save_to}/{game_id}', exist_ok=True)
3731
img.save(f'{STATIC_PATH}/images/{save_to}/{game_id}/{path}')
38-
cursor.execute(query, data)
39-
conn.commit()
40-
conn.close()
4132
except Exception as e:
42-
print(f'sqlite error:{e}')
43-
conn.rollback()
44-
conn.close()
33+
print(f'init pictures error:{e}')
4534
raise ValueError(str(e)) from e
4635

47-
def execute_sql_file(conn, sql_file):
48-
try:
49-
with open(sql_file, 'r', encoding='UTF-8') as file:
50-
sql_script = file.read()
51-
cursor = conn.cursor()
52-
cursor.executescript(sql_script)
53-
conn.commit()
54-
except sqlite3.Error as e:
55-
print(f'Execution sql error : {e}')
56-
conn.rollback()
57-
5836
def init_database():
5937
init_pics_csvs = [{
6038
'file': f'{INIT_CSV_PATH}/init-profile-pictures.csv',
6139
'table':'profiles_pictures',
6240
'save_to' : 'profiles'
63-
},{
41+
}, {
6442
'file': f'{INIT_CSV_PATH}/init-games-pictures.csv',
6543
'table':'games_pictures',
6644
'save_to' : 'games'
6745
}]
6846
try:
69-
_ = [init_from_csv(
70-
db_file=DB_PATH,
71-
csv_file=init_data['file'],
72-
table_name=init_data['table']
73-
) for init_data in init_csvs]
74-
7547
_ = [init_pics_from_csv(
76-
db_file=DB_PATH,
7748
csv_file=init_pics['file'],
7849
table_name=init_pics['table'],
7950
save_to=init_pics['save_to']
@@ -83,9 +54,19 @@ def init_database():
8354

8455
def get_db():
8556
if 'db' not in g:
86-
g.db = sqlite3.connect(DB_PATH)
87-
g.db.isolation_level = None
88-
g.db.row_factory = sqlite3.Row
57+
conn_params = {
58+
'host' : os.getenv('DB_HOST'),
59+
'port' : os.getenv('DB_PORT'),
60+
'dbname' : os.getenv('DB_NAME'),
61+
'user' : os.getenv('DB_USER'),
62+
'password': os.getenv('DB_PSWD'),
63+
'row_factory': psycopg.rows.dict_row
64+
}
65+
try:
66+
g.db = psycopg.connect(**conn_params)
67+
g.db.autocommit = True
68+
except psycopg.OperationalError as e:
69+
raise ValueError(f'Failed to connect to database: {e}')
8970
return g.db
9071

9172
def get_games_list(last_game_id:int, page_sz:int)->list[dict]:
@@ -95,20 +76,20 @@ def get_games_list(last_game_id:int, page_sz:int)->list[dict]:
9576
SELECT id
9677
FROM games
9778
ORDER BY id
98-
LIMIT (?);
79+
LIMIT %s;
9980
""", (page_sz,)) if last_game_id is None else ("""
10081
SELECT id
10182
FROM GAMES
102-
WHERE id > (?)
83+
WHERE id > %s
10384
ORDER BY id
104-
LIMIT (?);
85+
LIMIT %s;
10586
""", (last_game_id, page_sz,))
10687
cursor.execute(queue, params)
10788
game_ids = cursor.fetchall()
10889

10990
games = [get_game_info(game_id['id']) for game_id in game_ids]
11091
return games
111-
except sqlite3.Error as e:
92+
except psycopg.OperationalError as e:
11293
print(f'sql execution error {e}')
11394
return None
11495

@@ -122,7 +103,7 @@ def get_game_info(game_id:int)->dict:
122103
SELECT g.*, s.name AS studio_name
123104
FROM games g
124105
JOIN studios s ON s.id = g.studio_id
125-
WHERE g.id = (?);
106+
WHERE g.id = %s;
126107
""", (game_id,))
127108
data = cursor.fetchone()
128109
if data:
@@ -132,7 +113,7 @@ def get_game_info(game_id:int)->dict:
132113
else:
133114
print(game_id)
134115
return data
135-
except sqlite3.Error as e:
116+
except psycopg.Error as e:
136117
print(f'execute game query with id={game_id}:{e}')
137118
return None
138119

@@ -141,7 +122,7 @@ def check_user(user:User)->int:
141122
cursor = db.cursor()
142123
try:
143124
cursor.execute(
144-
'SELECT * FROM users WHERE name = (?);', (user.name,)
125+
'SELECT * FROM users WHERE name = %s;', (user.name,)
145126
)
146127
user_data = cursor.fetchone()
147128

@@ -153,7 +134,7 @@ def check_user(user:User)->int:
153134
return user_data['id'], user_data['balance']
154135
raise ValueError('Wrong password')
155136

156-
except sqlite3.Error as e:
137+
except psycopg.Error as e:
157138
raise ValueError(str(e)) from e
158139

159140
def add_user(user:User):
@@ -162,12 +143,12 @@ def add_user(user:User):
162143
try:
163144
cursor.execute("""
164145
INSERT INTO users (name, password_hash, balance)
165-
VALUES (?, ?, ?)
146+
VALUES (%s, %s, %s)
166147
""", (user.name, user.phash, 0))
167148
print('user add query was called')
168149
db.commit()
169-
except sqlite3.Error as e:
170-
print(f'sqlite3 error:{e}')
150+
except psycopg.Error as e:
151+
print(f'sql error:{e}')
171152
db.rollback()
172153
raise ValueError(str(e)) from e
173154

@@ -178,7 +159,7 @@ def get_profile_picture(user_id:int)->str:
178159
SELECT pp.name, pp.img_fmt
179160
FROM users u
180161
JOIN profiles_pictures pp ON u.id = pp.user_id
181-
WHERE u.id = ?;
162+
WHERE u.id = %s;
182163
""", (user_id,))
183164
user_pic = cursor.fetchone()
184165
if not user_pic:
@@ -187,7 +168,7 @@ def get_profile_picture(user_id:int)->str:
187168
user_pic = dict(user_pic)
188169
user_pic = user_pic['name'] if 'name' in user_pic else 'default.jpg'
189170
return user_pic
190-
except sqlite3.Error as e:
171+
except psycopg.Error as e:
191172
print(f'sql error:{e}')
192173
raise ValueError(str(e)) from e
193174

@@ -205,11 +186,11 @@ def get_user_games(user_id:int)->list[int]:
205186
cursor.execute("""
206187
SELECT game_id
207188
FROM purchases
208-
WHERE owner_id = (?) AND ts IS NOT NULL;
189+
WHERE owner_id = %s AND ts IS NOT NULL;
209190
""", (user_id,))
210191

211192
return [x['game_id'] for x in cursor.fetchall()]
212-
except sqlite3.Error as e:
193+
except psycopg.Error as e:
213194
print(f'sqlite error:{e}')
214195
raise ValueError(f'{e}') from e
215196

@@ -220,7 +201,7 @@ def get_tags_by_game_id(game_id:int)->list[str]:
220201
SELECT t.name
221202
FROM game_tags gt
222203
JOIN tags t ON gt.tag_id = t.id
223-
WHERE gt.game_id = ?;
204+
WHERE gt.game_id = %s;
224205
""", (game_id,))
225206
data = cursor.fetchall()
226207
tags = [tag['name'] for tag in data]
@@ -234,7 +215,7 @@ def get_pictures_by_game_id(game_id:int)->list[str]:
234215
cursor.execute("""
235216
SELECT name, img_type, img_fmt
236217
FROM games_pictures
237-
WHERE game_id = ?;
218+
WHERE game_id = %s;
238219
""", (game_id,))
239220
data = cursor.fetchall()
240221
return data
@@ -246,21 +227,21 @@ def buy_cart(user_id:int, total:int, games_ids:list[int]):
246227
cursor = conn.cursor()
247228
print(f'games_ids:{games_ids}')
248229
try:
249-
placeholders = ', '.join(['?'] * len(games_ids))
230+
placeholders = ', '.join(['%s'] * len(games_ids))
250231
# change purchases
251232
cursor.execute(f"""
252233
UPDATE purchases
253234
SET ts = STRFTIME('%s', 'now')
254-
WHERE owner_id = (?) AND game_id IN ({placeholders}) AND ts IS NULL;
235+
WHERE owner_id = %s AND game_id IN ({placeholders}) AND ts IS NULL;
255236
""", [user_id] + games_ids)
256237
# change balance
257238
cursor.execute("""
258239
UPDATE users
259-
SET balance = balance - (?)
260-
WHERE id = (?);
240+
SET balance = balance - %s
241+
WHERE id = %s;
261242
""", (total, user_id,))
262243
conn.commit()
263-
except sqlite3.Error as e:
244+
except psycopg.Error as e:
264245
conn.rollback()
265246
print('something went wrong')
266247
raise e from e
@@ -271,10 +252,10 @@ def remove_from_cart(user_id:int, game_id:int):
271252
try:
272253
cursor.execute("""
273254
DELETE FROM purchases
274-
WHERE owner_id = (?) AND game_id = (?) AND ts IS NULL;
255+
WHERE owner_id = %s AND game_id = %s AND ts IS NULL;
275256
""", (user_id, game_id,))
276257
conn.commit()
277-
except sqlite3.Error as e:
258+
except psycopg.Error as e:
278259
conn.rollback()
279260
raise ValueError(e) from e
280261

@@ -284,36 +265,36 @@ def get_user_cart_games(user_id:int)->list[dict]:
284265
cursor.execute("""
285266
SELECT game_id
286267
FROM purchases
287-
WHERE owner_id == (?) and ts IS NULL;
268+
WHERE owner_id == %s and ts IS NULL;
288269
""", (user_id,))
289270
data = cursor.fetchall()
290271
return data
291-
except sqlite3.error as e:
292-
raise ValueError(f'sqlite3 error: {e}') from e
272+
except psycopg.Error as e:
273+
raise ValueError(f'sql error: {e}') from e
293274

294275
def add_game_to_cart(user_id:int, game_id:int):
295276
conn = get_db()
296277
cursor = conn.cursor()
297278
try:
298279
cursor.execute("""
299280
INSERT INTO purchases (owner_id, buyer_id, ts, game_id)
300-
VALUES (?, ?, ?, ?);
281+
VALUES (%s, %s, %s, %s);
301282
""", (user_id, user_id, None, game_id,))
302283
conn.commit()
303-
except sqlite3.error as e:
284+
except psycopg.Error as e:
304285
conn.rollback()
305-
raise ValueError(f'sqlite3 error: {e}') from e
286+
raise ValueError(f'sql error: {e}') from e
306287

307288
def check_own_game(user_id:int, game_id:int)->bool:
308289
cursor = get_db().cursor()
309290
try:
310291
cursor.execute("""
311292
SELECT id FROM purchases
312-
WHERE game_id == (?) and owner_id == (?);
293+
WHERE game_id == %s and owner_id == %s;
313294
""", (game_id, user_id,))
314295
result = cursor.fetchone()
315296
if result :
316297
return True
317298
return False
318-
except sqlite3.error as e:
319-
raise ValueError(f'sqlite3 error: {e}') from e
299+
except psycopg.Error as e:
300+
raise ValueError(f'sql error: {e}') from e

0 commit comments

Comments
 (0)