-
Notifications
You must be signed in to change notification settings - Fork 0
first try #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
first try #1
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ package main | |
|
|
||
| import ( | ||
| "database/sql" | ||
| "fmt" | ||
| ) | ||
|
|
||
| type ParcelStore struct { | ||
|
|
@@ -13,48 +14,121 @@ func NewParcelStore(db *sql.DB) ParcelStore { | |
| } | ||
|
|
||
| func (s ParcelStore) Add(p Parcel) (int, error) { | ||
| // реализуйте добавление строки в таблицу parcel, используйте данные из переменной p | ||
|
|
||
| // верните идентификатор последней добавленной записи | ||
| return 0, nil | ||
| res, err := s.db.Exec("INSERT INTO parcel (client, status, address, created_at) VALUES ( :client, :status, :address, :createdAt)", | ||
| sql.Named("client", p.Client), | ||
| sql.Named("status", p.Status), | ||
| sql.Named("address", p.Address), | ||
| sql.Named("createdAt", p.CreatedAt)) | ||
| if err != nil { | ||
| return 0, fmt.Errorf("insert failed: %w", err) | ||
| } | ||
|
|
||
| id, err := res.LastInsertId() | ||
| if err != nil { | ||
| return 0, fmt.Errorf("scan id failed: %w", err) | ||
| } | ||
|
|
||
| return int(id), nil | ||
|
|
||
| } | ||
|
|
||
| func (s ParcelStore) Get(number int) (Parcel, error) { | ||
| // реализуйте чтение строки по заданному number | ||
| // здесь из таблицы должна вернуться только одна строка | ||
|
|
||
| // заполните объект Parcel данными из таблицы | ||
| p := Parcel{} | ||
| row := s.db.QueryRow("SELECT number, client, status, address, created_at FROM parcel WHERE number = :number", sql.Named("number", number)) | ||
| err := row.Scan(&p.Number, &p.Client, &p.Status, &p.Address, &p.CreatedAt) | ||
| if err != nil { | ||
| return Parcel{}, fmt.Errorf("select error: %w", err) | ||
| } | ||
|
|
||
| return p, nil | ||
| } | ||
|
|
||
| func (s ParcelStore) GetByClient(client int) ([]Parcel, error) { | ||
| // реализуйте чтение строк из таблицы parcel по заданному client | ||
| // здесь из таблицы может вернуться несколько строк | ||
| rows, err := s.db.Query(`SELECT number, client, status, address, created_at FROM parcel WHERE client = :client`, sql.Named("client", client)) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("select failed: %w", err) | ||
| } | ||
| defer rows.Close() | ||
|
|
||
| // заполните срез Parcel данными из таблицы | ||
| var res []Parcel | ||
|
|
||
| for rows.Next() { | ||
| p := Parcel{} | ||
|
|
||
| err := rows.Scan(&p.Number, &p.Client, &p.Status, &p.Address, &p.CreatedAt) | ||
| if err != nil { | ||
|
|
||
| return res, fmt.Errorf("scan failed: %w", err) | ||
| } | ||
|
|
||
| res = append(res, p) | ||
| } | ||
| if err := rows.Err(); err != nil { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 коректная работа с БД - проверка ошибки и rows закрываешь - отлично.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. на 68 строке, как я поняла проверяется, что построчное чтение rows прошло успешно, без прерывания цикла rows.Nex(). так? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Да, все так, проверяем что все верно вычитано без ошибок |
||
| return nil, fmt.Errorf("rows unpacking failed: %w", err) | ||
| } | ||
|
|
||
| return res, nil | ||
| } | ||
|
|
||
| func (s ParcelStore) SetStatus(number int, status string) error { | ||
| // реализуйте обновление статуса в таблице parcel | ||
|
|
||
| _, err := s.db.Exec("UPDATE parcel SET status = :status WHERE number = :number", | ||
| sql.Named("status", status), | ||
| sql.Named("number", number)) | ||
| if err != nil { | ||
| return fmt.Errorf("update failed: %w", err) | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| func (s ParcelStore) GetStatus(number int) (string, error) { | ||
| // не хочу повторять код в двух других функциях, поэтому отдельно реализовала получение статуса | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Хорошее решение. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (важно понимать что это будет дополнительный запрос. Бывают ситуации, когда нам важано ускориться и не делать лишние запросы. Тогда можно проверку статуса унести в основной запрос (например Update), в условие
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Например так? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Да, так |
||
| p := Parcel{} | ||
| row := s.db.QueryRow("SELECT status FROM parcel WHERE number = :number", sql.Named("number", number)) | ||
| err := row.Scan(&p.Status) | ||
| if err != nil { | ||
| return "", fmt.Errorf("select failed: %w", err) | ||
| } | ||
|
|
||
| return p.Status, nil | ||
|
|
||
| } | ||
| func (s ParcelStore) SetAddress(number int, address string) error { | ||
| // реализуйте обновление адреса в таблице parcel | ||
| // менять адрес можно только если значение статуса registered | ||
|
|
||
| status, err := s.GetStatus(number) | ||
| if err != nil { | ||
| return fmt.Errorf("getStatus failed: %w", err) | ||
| } | ||
|
|
||
| if status != ParcelStatusRegistered { | ||
| return fmt.Errorf("address shouldn't be updated") // не знаю что возвратить | ||
| } | ||
| _, err = s.db.Exec("UPDATE parcel SET address = :address WHERE number = :number", | ||
| sql.Named("address", address), | ||
| sql.Named("number", number)) | ||
| if err != nil { | ||
| return fmt.Errorf("update failed: %w", err) | ||
| } | ||
| return nil | ||
|
|
||
| } | ||
|
|
||
| func (s ParcelStore) Delete(number int) error { | ||
| // реализуйте удаление строки из таблицы parcel | ||
| // удалять строку можно только если значение статуса registered | ||
| status, err := s.GetStatus(number) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| if status != ParcelStatusRegistered { | ||
| return fmt.Errorf("parcel shouldn't be deleted") | ||
| } | ||
|
|
||
| _, err = s.db.Exec("DELETE FROM parcel WHERE number = :number", sql.Named("number", number)) | ||
| return fmt.Errorf("delete failed: %w", err) | ||
|
|
||
| return nil | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Хорошая формулировка, понятно что именно упало