- Timestamp:
- 09/24/26 17:43:19 (5 days ago)
- Branches:
- main
- Children:
- 0cee8ec
- Parents:
- a531b45
- Location:
- server/db
- Files:
-
- 3 added
- 4 edited
-
advanced_db.sql (added)
-
advanced_db_tests.sql (added)
-
data_load.sql (modified) (4 diffs)
-
db.go (modified) (4 diffs)
-
reports_demo_data.sql (modified) (2 diffs)
-
schema_creation.sql (modified) (3 diffs)
-
ssh.go (added)
Legend:
- Unmodified
- Added
- Removed
-
server/db/data_load.sql
ra531b45 ref1c1c7 8 8 -- 9 9 -- All sample users have the password: test123 10 -- 11 -- One transaction: the P7 checks in advanced_db.sql compare balances with 12 -- the ledger at COMMIT, and the users are inserted with their balances 13 -- before the deposit rows that back them. In an auto-commit client 14 -- (DBeaver) every statement would otherwise be checked on its own. 15 16 BEGIN; 10 17 11 18 SET search_path TO project, public; … … 104 111 -- Shows a fully-filled market buy and its resulting holding & ledger entry. 105 112 -- ============================================================================ 106 INSERT INTO project.orders (id, user_id, market_id, side, type, status, quantity, price, placed_at, executed_at) VALUES 113 -- Imported as already completely filled (filled_quantity = quantity). 114 INSERT INTO project.orders (id, user_id, market_id, side, type, status, quantity, filled_quantity, price, placed_at, executed_at) VALUES 107 115 ('c1111111-1111-1111-1111-111111111111', 108 116 'b1111111-1111-1111-1111-111111111111', 109 117 'a2222222-2222-2222-2222-222222222222', 110 'buy', 'market', 'executed', 0.5000, 3500.000000,118 'buy', 'market', 'executed', 0.5000, 0.5000, 3500.000000, 111 119 now() - interval '1 hour', now() - interval '1 hour'); 112 120 … … 118 126 INSERT INTO project.transactions (user_id, type, amount, currency, related_order, description) VALUES 119 127 ('b1111111-1111-1111-1111-111111111111', 'deposit', 10000.0000, 'USD', NULL, 128 'Initial virtual deposit'), 129 ('b2222222-2222-2222-2222-222222222222', 'deposit', 5000.0000, 'USD', NULL, 130 'Initial virtual deposit'), 131 ('b3333333-3333-3333-3333-333333333333', 'deposit', 2500.0000, 'USD', NULL, 120 132 'Initial virtual deposit'), 121 133 ('b1111111-1111-1111-1111-111111111111', 'buy', -1750.0000, 'USD', … … 143 155 ('d2222222-2222-2222-2222-222222222222', '11111111-1111-1111-1111-111111111111'), 144 156 ('d2222222-2222-2222-2222-222222222222', '55555555-5555-5555-5555-555555555555'); 157 158 COMMIT; -
server/db/db.go
ra531b45 ref1c1c7 11 11 "strings" 12 12 13 _"github.com/lib/pq"13 "github.com/lib/pq" 14 14 ) 15 15 … … 19 19 // which directory the program is started from. 20 20 // 21 //go:embed schema_creation.sql data_load.sql21 //go:embed schema_creation.sql advanced_db.sql data_load.sql 22 22 var sqlScripts embed.FS 23 23 … … 36 36 ) 37 37 38 var err error 39 DB, err = sql.Open("postgres", dsn) 40 if err != nil { 41 return fmt.Errorf("sql.Open: %w", err) 38 // Optional SSH tunnel, the same thing DBeaver's "SSH" tab does. When 39 // SSH_HOST is set, DBHOST/DBPORT are resolved from the SSH server's side 40 // (for the faculty server that is usually localhost:5432). 41 if sshHost := os.Getenv("SSH_HOST"); sshHost != "" { 42 dialer, err := newSSHDialer(sshHost) 43 if err != nil { 44 return err 45 } 46 connector, err := pq.NewConnector(dsn) 47 if err != nil { 48 return fmt.Errorf("pq.NewConnector: %w", err) 49 } 50 connector.Dialer(dialer) 51 DB = sql.OpenDB(connector) 52 } else { 53 var err error 54 DB, err = sql.Open("postgres", dsn) 55 if err != nil { 56 return fmt.Errorf("sql.Open: %w", err) 57 } 42 58 } 43 59 if err := DB.Ping(); err != nil { … … 72 88 } 73 89 74 // InitSchema runs schema_creation.sql thendata_load.sql.90 // InitSchema runs schema_creation.sql, advanced_db.sql (P7) and data_load.sql. 75 91 // Destructive: drops the `project` schema. Intended for the -init flag. 76 92 func InitSchema() error { 77 log.Println("Running schema_creation.sql ...") 78 if err := runScript("schema_creation.sql"); err != nil { 79 return err 93 for _, name := range []string{"schema_creation.sql", "advanced_db.sql"} { 94 log.Printf("Running %s ...", name) 95 if err := runScript(name); err != nil { 96 return err 97 } 80 98 } 81 99 if err := LoadData(); err != nil { -
server/db/reports_demo_data.sql
ra531b45 ref1c1c7 28 28 -- description/source) before re-inserting. 29 29 30 -- P7: users' cash (available + reserved) must equal their ledger at 31 -- COMMIT, so the balance moves by exactly what this script removes and 32 -- re-adds to the ledger, all in one transaction. The historical orders are 33 -- imported as completely filled. 34 35 BEGIN; 36 30 37 SET search_path TO project, public; 38 39 UPDATE users u 40 SET available_balance = u.available_balance - d.total 41 FROM (SELECT user_id, SUM(amount) AS total FROM transactions 42 WHERE description = 'P6 demo data' GROUP BY user_id) d 43 WHERE u.id = d.user_id; 31 44 32 45 DELETE FROM transactions WHERE description = 'P6 demo data'; … … 98 111 -- Executed orders: who participated in which market, across the same quarters. 99 112 -- ============================================================================ 100 INSERT INTO orders (id, user_id, market_id, side, type, status, quantity, price, placed_at, executed_at) VALUES113 INSERT INTO orders (id, user_id, market_id, side, type, status, quantity, filled_quantity, price, placed_at, executed_at) VALUES 101 114 ('e1111111-1111-1111-1111-111111111111', 'b1111111-1111-1111-1111-111111111111', 102 'a1111111-1111-1111-1111-111111111111', 'buy', 'market', 'executed', 0.5000, 40000.000000,115 'a1111111-1111-1111-1111-111111111111', 'buy', 'market', 'executed', 0.5000, 0.5000, 40000.000000, 103 116 '2025-07-15 10:00', '2025-07-15 10:00'), 104 117 ('e2222222-2222-2222-2222-222222222222', 'b1111111-1111-1111-1111-111111111111', 105 'a2222222-2222-2222-2222-222222222222', 'sell', 'market', 'executed', 3.0000, 4000.000000,118 'a2222222-2222-2222-2222-222222222222', 'sell', 'market', 'executed', 3.0000, 3.0000, 4000.000000, 106 119 '2025-10-15 10:00', '2025-10-15 10:00'), 107 120 ('e3333333-3333-3333-3333-333333333333', 'b2222222-2222-2222-2222-222222222222', 108 'a1111111-1111-1111-1111-111111111111', 'buy', 'market', 'executed', 1.2000, 55000.000000,121 'a1111111-1111-1111-1111-111111111111', 'buy', 'market', 'executed', 1.2000, 1.2000, 55000.000000, 109 122 '2026-01-15 10:00', '2026-01-15 10:00'), 110 123 ('e4444444-4444-4444-4444-444444444444', 'b2222222-2222-2222-2222-222222222222', 111 'a1111111-1111-1111-1111-111111111111', 'buy', 'market', 'executed', 1.0000, 60000.000000,124 'a1111111-1111-1111-1111-111111111111', 'buy', 'market', 'executed', 1.0000, 1.0000, 60000.000000, 112 125 '2026-04-15 10:00', '2026-04-15 10:00'), 113 126 ('e5555555-5555-5555-5555-555555555555', 'b3333333-3333-3333-3333-333333333333', 114 'a2222222-2222-2222-2222-222222222222', 'sell', 'market', 'executed', 2.0000, 3600.000000,127 'a2222222-2222-2222-2222-222222222222', 'sell', 'market', 'executed', 2.0000, 2.0000, 3600.000000, 115 128 '2026-01-15 10:00', '2026-01-15 10:00'); 129 130 UPDATE users u 131 SET available_balance = u.available_balance + d.total 132 FROM (SELECT user_id, SUM(amount) AS total FROM transactions 133 WHERE description = 'P6 demo data' GROUP BY user_id) d 134 WHERE u.id = d.user_id; 135 136 COMMIT; -
server/db/schema_creation.sql
ra531b45 ref1c1c7 26 26 available_balance numeric(18,4) NOT NULL DEFAULT 0 CHECK (available_balance >= 0), 27 27 invested_balance numeric(18,4) NOT NULL DEFAULT 0 CHECK (invested_balance >= 0), 28 -- P7: cash committed to the user's active buy orders, moved out of 29 -- available_balance when the order is placed and consumed as it fills. 30 reserved_balance numeric(18,4) NOT NULL DEFAULT 0 CHECK (reserved_balance >= 0), 28 31 created_at timestamptz NOT NULL DEFAULT now(), 29 32 updated_at timestamptz … … 86 89 side varchar(4) NOT NULL CHECK (side IN ('buy', 'sell')), 87 90 type varchar(20) NOT NULL CHECK (type IN ('market', 'limit')), 88 status varchar(20) NOT NULL CHECK (status IN ('open', ' executed', 'cancelled')),91 status varchar(20) NOT NULL CHECK (status IN ('open', 'partially_filled', 'executed', 'cancelled')), 89 92 quantity numeric(20,4) NOT NULL CHECK (quantity > 0), 93 -- P7: how much of the order has been traded so far; remaining is 94 -- quantity - filled_quantity. Maintained from market_trades. 95 filled_quantity numeric(20,4) NOT NULL DEFAULT 0 96 CHECK (filled_quantity >= 0 AND filled_quantity <= quantity), 90 97 price numeric(18,6), 91 98 placed_at timestamptz NOT NULL DEFAULT now(), … … 125 132 quantity numeric(20,6) NOT NULL CHECK (quantity > 0), 126 133 side varchar(4) CHECK (side IN ('buy', 'sell')), 127 source varchar(50) NOT NULL DEFAULT 'simulation' 134 source varchar(50) NOT NULL DEFAULT 'simulation', 135 -- P7: the orders this trade filled. NULL on a side means the counterparty 136 -- was the simulated market (bot ticks have both NULL). 137 buy_order_id uuid REFERENCES project.orders(id), 138 sell_order_id uuid REFERENCES project.orders(id) 128 139 ); 129 140 130 141 CREATE INDEX idx_market_trades_market_time ON project.market_trades(market_id, executed_at DESC); 142 CREATE INDEX idx_market_trades_buy_order ON project.market_trades(buy_order_id) WHERE buy_order_id IS NOT NULL; 143 CREATE INDEX idx_market_trades_sell_order ON project.market_trades(sell_order_id) WHERE sell_order_id IS NOT NULL; 131 144 132 145 -- ============================================================================
Note:
See TracChangeset
for help on using the changeset viewer.
