Skip to main content

max / makenotwork

20.9 KB · 351 lines History Blame Raw
1 -- Test data seed script
2 -- Creates edge case data to test sanitization, pagination, and error handling
3 -- All accounts use password: "testpassword123"
4
5 -- Password hash for "testpassword123" (argon2id)
6 -- Reusing existing hash from database
7 \set pwd_hash '$argon2id$v=19$m=19456,t=2,p=1$DKKe+bI4TwiyxkLgyCDZMA$oXVcdLHZIxv1hkFGK4JB5HNqoGURavSXhY9gjmvQeEM'
8
9 -- =============================================================================
10 -- USERS - Edge cases for usernames, display names, bios
11 -- =============================================================================
12
13 -- Normal users for pagination
14 INSERT INTO users (username, email, password_hash, display_name, bio) VALUES
15 ('alice', 'alice@test.com', :'pwd_hash', 'Alice Anderson', 'Just a normal bio.'),
16 ('bob', 'bob@test.com', :'pwd_hash', 'Bob Builder', 'Building things since 1999.'),
17 ('carol', 'carol@test.com', :'pwd_hash', 'Carol Chen', 'Music producer and sound designer.'),
18 ('dave', 'dave@test.com', :'pwd_hash', 'Dave Davidson', 'Writer, podcaster, occasional human.'),
19 ('emma', 'emma@test.com', :'pwd_hash', 'Emma Edwards', 'Digital artist exploring new frontiers.'),
20 ('frank', 'frank@test.com', :'pwd_hash', 'Frank Fitzgerald', 'Composer for film and games.'),
21 ('grace', 'grace@test.com', :'pwd_hash', 'Grace Garcia', 'Photographer and visual storyteller.'),
22 ('henry', 'henry@test.com', :'pwd_hash', 'Henry Huang', 'Making beats in my bedroom.'),
23 ('iris', 'iris@test.com', :'pwd_hash', 'Iris Ibrahim', 'Author of several unpublished novels.'),
24 ('jack', 'jack@test.com', :'pwd_hash', 'Jack Johnson', 'Not the singer, the other one.');
25
26 -- Long display name (exactly 100 chars)
27 INSERT INTO users (username, email, password_hash, display_name, bio) VALUES
28 ('longname', 'longname@test.com', :'pwd_hash',
29 'This Is A Very Long Display Name That Goes All The Way To The Maximum Allowed Length Of One Hundred!',
30 'Testing maximum length display names.');
31
32 -- Unicode/International names
33 INSERT INTO users (username, email, password_hash, display_name, bio) VALUES
34 ('unicode1', 'unicode1@test.com', :'pwd_hash', 'Müller Strøm', 'Scandinavian characters in name.'),
35 ('unicode2', 'unicode2@test.com', :'pwd_hash', '中文用户', 'Chinese display name.'),
36 ('unicode3', 'unicode3@test.com', :'pwd_hash', 'Владимир', 'Russian Cyrillic name.'),
37 ('unicode4', 'unicode4@test.com', :'pwd_hash', 'محمد', 'Arabic name (RTL text).'),
38 ('unicode5', 'unicode5@test.com', :'pwd_hash', '田中太郎', 'Japanese name.'),
39 ('unicode6', 'unicode6@test.com', :'pwd_hash', 'Σωκράτης', 'Greek name.');
40
41 -- HTML/Script injection attempts in display name
42 INSERT INTO users (username, email, password_hash, display_name, bio) VALUES
43 ('xss1', 'xss1@test.com', :'pwd_hash', '<script>alert("xss")</script>', 'Script tag in display name.'),
44 ('xss2', 'xss2@test.com', :'pwd_hash', '"><img src=x onerror=alert(1)>', 'Image onerror injection.'),
45 ('xss3', 'xss3@test.com', :'pwd_hash', '<iframe src="evil.com"></iframe>', 'Iframe injection attempt.'),
46 ('xss4', 'xss4@test.com', :'pwd_hash', 'onclick="alert(1)"', 'Event handler injection.'),
47 ('xss5', 'xss5@test.com', :'pwd_hash', '<svg onload=alert(1)>', 'SVG injection.'),
48 ('xss6', 'xss6@test.com', :'pwd_hash', 'javascript:alert(1)', 'JavaScript protocol.'),
49 ('xss7', 'xss7@test.com', :'pwd_hash', '<a href="javascript:void(0)">click</a>', 'Link with JS href.'),
50 ('xss8', 'xss8@test.com', :'pwd_hash', '&lt;script&gt;encoded&lt;/script&gt;', 'HTML encoded script.');
51
52 -- SQL injection attempts in bio (should be safely stored as text)
53 INSERT INTO users (username, email, password_hash, display_name, bio) VALUES
54 ('sqli1', 'sqli1@test.com', :'pwd_hash', 'SQL Tester 1', E'Bio with quote: O''Reilly'),
55 ('sqli2', 'sqli2@test.com', :'pwd_hash', 'SQL Tester 2', 'SELECT * FROM users; DROP TABLE users;--'),
56 ('sqli3', 'sqli3@test.com', :'pwd_hash', 'SQL Tester 3', E'1\' OR \'1\'=\'1'),
57 ('sqli4', 'sqli4@test.com', :'pwd_hash', 'SQL Tester 4', '1; UPDATE users SET email=''hacked@evil.com'''),
58 ('sqli5', 'sqli5@test.com', :'pwd_hash', 'SQL Tester 5', 'UNION SELECT password_hash FROM users');
59
60 -- Special characters
61 INSERT INTO users (username, email, password_hash, display_name, bio) VALUES
62 ('special1', 'special1@test.com', :'pwd_hash', 'Back\slash', 'Backslash in name.'),
63 ('special2', 'special2@test.com', :'pwd_hash', 'Percent%Sign', 'Percent sign in name.'),
64 ('special3', 'special3@test.com', :'pwd_hash', 'Ampersand&Co', 'Ampersand in name.'),
65 ('special4', 'special4@test.com', :'pwd_hash', 'Less<Than', 'Less than in name.'),
66 ('special5', 'special5@test.com', :'pwd_hash', 'Greater>Than', 'Greater than in name.'),
67 ('special6', 'special6@test.com', :'pwd_hash', 'Quote"Mark', 'Double quote in name.'),
68 ('special7', 'special7@test.com', :'pwd_hash', E'Single\'Quote', 'Single quote in name.'),
69 ('special8', 'special8@test.com', :'pwd_hash', 'Null' || chr(0) || 'Byte', 'Null byte injection attempt.'),
70 ('special9', 'special9@test.com', :'pwd_hash', E'New\nLine', 'Newline in display name.'),
71 ('special10', 'special10@test.com', :'pwd_hash', E'Tab\tChar', 'Tab character in name.');
72
73 -- Whitespace edge cases
74 INSERT INTO users (username, email, password_hash, display_name, bio) VALUES
75 ('whitespace1', 'whitespace1@test.com', :'pwd_hash', ' Leading Spaces', 'Leading spaces in name.'),
76 ('whitespace2', 'whitespace2@test.com', :'pwd_hash', 'Trailing Spaces ', 'Trailing spaces in name.'),
77 ('whitespace3', 'whitespace3@test.com', :'pwd_hash', 'Multiple Spaces', 'Multiple internal spaces.'),
78 ('whitespace4', 'whitespace4@test.com', :'pwd_hash', ' ', 'Only spaces as name.');
79
80 -- Homograph attacks (lookalike characters)
81 INSERT INTO users (username, email, password_hash, display_name, bio) VALUES
82 ('homograph1', 'homograph1@test.com', :'pwd_hash', 'Аdmin', 'Cyrillic A looks like Latin A.'),
83 ('homograph2', 'homograph2@test.com', :'pwd_hash', 'pаypal', 'Cyrillic a in paypal.'),
84 ('homograph3', 'homograph3@test.com', :'pwd_hash', 'gооgle', 'Cyrillic o in google.');
85
86 -- Very long bio
87 INSERT INTO users (username, email, password_hash, display_name, bio) VALUES
88 ('longbio', 'longbio@test.com', :'pwd_hash', 'Long Bio User',
89 'This is a very long bio that goes on and on. ' ||
90 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. ' ||
91 'Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ' ||
92 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris. ' ||
93 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum. ' ||
94 'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia. ' ||
95 repeat('More text to make this bio really really long. ', 50));
96
97 -- Zero-width characters
98 INSERT INTO users (username, email, password_hash, display_name, bio) VALUES
99 ('zerowidth', 'zerowidth@test.com', :'pwd_hash',
100 'Invi' || E'\u200B' || 'sible', 'Zero-width space in name.');
101
102 -- =============================================================================
103 -- PROJECTS - Edge cases for titles, slugs, descriptions
104 -- =============================================================================
105
106 -- Get user IDs for inserting projects
107 DO $$
108 DECLARE
109 alice_id UUID;
110 bob_id UUID;
111 xss1_id UUID;
112 sqli1_id UUID;
113 unicode1_id UUID;
114 BEGIN
115 SELECT id INTO alice_id FROM users WHERE username = 'alice';
116 SELECT id INTO bob_id FROM users WHERE username = 'bob';
117 SELECT id INTO xss1_id FROM users WHERE username = 'xss1';
118 SELECT id INTO sqli1_id FROM users WHERE username = 'sqli1';
119 SELECT id INTO unicode1_id FROM users WHERE username = 'unicode1';
120
121 -- Normal projects for alice (pagination testing)
122 INSERT INTO projects (user_id, slug, title, description, project_type) VALUES
123 (alice_id, 'album-one', 'First Album', 'My debut album with 10 tracks.', 'music'),
124 (alice_id, 'album-two', 'Second Album', 'Follow-up with new sounds.', 'music'),
125 (alice_id, 'album-three', 'Third Album', 'Experimental phase.', 'music'),
126 (alice_id, 'singles-2024', 'Singles 2024', 'All my singles from this year.', 'music'),
127 (alice_id, 'remixes', 'Remix Collection', 'Remixes of popular tracks.', 'music'),
128 (alice_id, 'podcast', 'The Alice Show', 'Weekly podcast about music production.', 'podcast'),
129 (alice_id, 'tutorials', 'Production Tutorials', 'Learn how I make my sounds.', 'education'),
130 (alice_id, 'samples', 'Sample Packs', 'Free and paid sample packs.', 'samples'),
131 (alice_id, 'collabs', 'Collaborations', 'Projects with other artists.', 'music'),
132 (alice_id, 'live-sessions', 'Live Sessions', 'Recordings from live performances.', 'music');
133
134 -- Normal projects for bob
135 INSERT INTO projects (user_id, slug, title, description, project_type) VALUES
136 (bob_id, 'construction-beats', 'Construction Beats', 'Heavy industrial sounds.', 'music'),
137 (bob_id, 'ambient-works', 'Ambient Works', 'Chill background music.', 'music'),
138 (bob_id, 'field-recordings', 'Field Recordings', 'Sounds from construction sites.', 'samples');
139
140 -- Long title (200 chars)
141 INSERT INTO projects (user_id, slug, title, description, project_type) VALUES
142 (alice_id, 'long-title-project',
143 'This Is An Extremely Long Project Title That Stretches All The Way To The Maximum Allowed Character Limit Of Two Hundred Characters Which Is Quite A Lot Of Text To Fit In A Single Title Field Here!!',
144 'Testing maximum length project titles.', 'general');
145
146 -- XSS attempts in project titles
147 INSERT INTO projects (user_id, slug, title, description, project_type) VALUES
148 (xss1_id, 'xss-project-1', '<script>alert("project")</script>', 'Script in title.', 'general'),
149 (xss1_id, 'xss-project-2', '<img src=x onerror=alert(1)>', 'Image onerror in title.', 'general'),
150 (xss1_id, 'xss-project-3', '"><marquee>hacked</marquee>', 'Marquee injection.', 'general'),
151 (xss1_id, 'xss-project-4', '<style>body{display:none}</style>', 'Style injection.', 'general');
152
153 -- XSS in project description (markdown field - more dangerous)
154 INSERT INTO projects (user_id, slug, title, description, project_type) VALUES
155 (xss1_id, 'xss-desc-1', 'XSS Description Test 1', '<script>document.cookie</script>', 'general'),
156 (xss1_id, 'xss-desc-2', 'XSS Description Test 2', '[Click me](javascript:alert(1))', 'general'),
157 (xss1_id, 'xss-desc-3', 'XSS Description Test 3', '![img](x" onerror="alert(1))', 'general'),
158 (xss1_id, 'xss-desc-4', 'XSS Description Test 4', '<details open ontoggle=alert(1)>', 'general');
159
160 -- SQL injection in titles
161 INSERT INTO projects (user_id, slug, title, description, project_type) VALUES
162 (sqli1_id, 'sqli-project-1', E'O\'Reilly Media', 'Quote in title.', 'general'),
163 (sqli1_id, 'sqli-project-2', 'DROP TABLE projects;--', 'SQL drop table.', 'general'),
164 (sqli1_id, 'sqli-project-3', '1; DELETE FROM users WHERE 1=1', 'SQL delete.', 'general');
165
166 -- Unicode project titles
167 INSERT INTO projects (user_id, slug, title, description, project_type) VALUES
168 (unicode1_id, 'japanese-album', '夜の音楽', 'Japanese title: Night Music.', 'music'),
169 (unicode1_id, 'arabic-album', 'موسيقى الليل', 'Arabic title: Night Music.', 'music'),
170 (unicode1_id, 'emoji-album', 'Night Vibes 🌙✨🎵', 'Emoji in title.', 'music'),
171 (unicode1_id, 'mixed-scripts', 'Mix: 音楽 & Музыка', 'Mixed Japanese and Russian.', 'music');
172
173 -- Long slug
174 INSERT INTO projects (user_id, slug, title, description, project_type) VALUES
175 (alice_id, 'this-is-an-extremely-long-slug-that-approaches-the-maximum-allowed-length-for-slugs-in-the-database',
176 'Long Slug Project', 'Testing long slugs.', 'general');
177
178 -- Edge case descriptions
179 INSERT INTO projects (user_id, slug, title, description, project_type) VALUES
180 (alice_id, 'no-description', 'No Description', NULL, 'general'),
181 (alice_id, 'empty-description', 'Empty Description', '', 'general'),
182 (alice_id, 'whitespace-desc', 'Whitespace Only', ' ', 'general'),
183 (alice_id, 'markdown-desc', 'Markdown Description',
184 E'# Heading 1\n## Heading 2\n**Bold** and *italic*\n\n- List item 1\n- List item 2\n\n```code block```\n\n[Link](https://example.com)',
185 'general');
186
187 END $$;
188
189 -- =============================================================================
190 -- ITEMS - Edge cases for titles, descriptions, prices, tags
191 -- =============================================================================
192
193 DO $$
194 DECLARE
195 proj_id UUID;
196 xss_proj_id UUID;
197 sqli_proj_id UUID;
198 BEGIN
199 -- Get a project ID for alice
200 SELECT id INTO proj_id FROM projects WHERE slug = 'album-one' LIMIT 1;
201 SELECT id INTO xss_proj_id FROM projects WHERE slug = 'xss-project-1' LIMIT 1;
202 SELECT id INTO sqli_proj_id FROM projects WHERE slug = 'sqli-project-1' LIMIT 1;
203
204 -- Normal items for pagination (in album-one)
205 INSERT INTO items (project_id, title, description, price_cents, item_type, tags, sort_order, is_public) VALUES
206 (proj_id, 'Track 01 - Intro', 'Opening track of the album.', 0, 'audio', '["intro", "ambient"]', 1, true),
207 (proj_id, 'Track 02 - Rise', 'Energy builds in this track.', 199, 'audio', '["electronic", "upbeat"]', 2, true),
208 (proj_id, 'Track 03 - Peak', 'The climax of the album.', 299, 'audio', '["electronic", "intense"]', 3, true),
209 (proj_id, 'Track 04 - Fall', 'Winding down.', 199, 'audio', '["ambient", "chill"]', 4, true),
210 (proj_id, 'Track 05 - Outro', 'Closing thoughts.', 0, 'audio', '["outro", "ambient"]', 5, true),
211 (proj_id, 'Bonus - Demo Version', 'Early demo of Track 03.', 0, 'audio', '["bonus", "demo"]', 6, true),
212 (proj_id, 'Album Artwork', 'High-res album cover.', 0, 'download', '["artwork", "image"]', 7, true),
213 (proj_id, 'Liner Notes', 'Thoughts behind each track.', 0, 'text', '["notes", "text"]', 8, true),
214 (proj_id, 'Full Album Bundle', 'All tracks in one download.', 999, 'download', '["bundle", "album"]', 9, true),
215 (proj_id, 'Stems Pack', 'Individual stems for remixing.', 1999, 'download', '["stems", "remix"]', 10, true);
216
217 -- Draft items (not public)
218 INSERT INTO items (project_id, title, description, price_cents, item_type, tags, sort_order, is_public) VALUES
219 (proj_id, 'Unreleased Track', 'Not ready yet.', 0, 'audio', '["unreleased"]', 11, false),
220 (proj_id, 'Work in Progress', 'Still mixing.', 499, 'audio', '["wip"]', 12, false);
221
222 -- Edge case prices
223 INSERT INTO items (project_id, title, description, price_cents, item_type, tags, sort_order, is_public) VALUES
224 (proj_id, 'One Cent Item', 'Cheapest possible.', 1, 'audio', '["cheap"]', 13, true),
225 (proj_id, 'Expensive Item', 'Premium content.', 99999, 'audio', '["premium"]', 14, true),
226 (proj_id, 'Very Expensive', 'Exclusive content.', 999999, 'audio', '["exclusive"]', 15, true);
227
228 -- Long title (200 chars)
229 INSERT INTO items (project_id, title, description, price_cents, item_type, tags, sort_order, is_public) VALUES
230 (proj_id,
231 'This Is An Incredibly Long Track Title That Goes On And On And Reaches The Maximum Character Limit For Item Titles Which Is Two Hundred Characters Long This Should Test Title Truncation Properly Now!!',
232 'Testing maximum length item titles.', 0, 'audio', '["test"]', 16, true);
233
234 -- XSS in item titles
235 INSERT INTO items (project_id, title, description, price_cents, item_type, tags, sort_order, is_public) VALUES
236 (xss_proj_id, '<script>alert("item")</script>', 'Script in item title.', 0, 'audio', '[]', 1, true),
237 (xss_proj_id, '<img src=x onerror=alert(1)>', 'Image onerror in item title.', 0, 'audio', '[]', 2, true),
238 (xss_proj_id, 'Normal Title', '<script>alert("desc")</script>', 0, 'text', '[]', 3, true),
239 (xss_proj_id, 'Markdown XSS', '[Click](javascript:alert(1))', 0, 'text', '[]', 4, true);
240
241 -- XSS in tags (JSON)
242 INSERT INTO items (project_id, title, description, price_cents, item_type, tags, sort_order, is_public) VALUES
243 (xss_proj_id, 'XSS Tags Test', 'XSS in tags.', 0, 'audio',
244 '["<script>alert(1)</script>", "normal", "<img src=x>"]', 5, true);
245
246 -- SQL injection in item content
247 INSERT INTO items (project_id, title, description, price_cents, item_type, tags, sort_order, is_public) VALUES
248 (sqli_proj_id, E'O\'Reilly Track', 'Quote in title.', 0, 'audio', '[]', 1, true),
249 (sqli_proj_id, 'DROP TABLE items;', 'SQL drop.', 0, 'audio', '[]', 2, true),
250 (sqli_proj_id, 'Normal Title', '1; DELETE FROM items;--', 0, 'audio', '[]', 3, true);
251
252 -- Unicode item titles
253 INSERT INTO items (project_id, title, description, price_cents, item_type, tags, sort_order, is_public) VALUES
254 (proj_id, '夜の音 (Night Sound)', 'Japanese title.', 0, 'audio', '["japanese"]', 17, true),
255 (proj_id, 'موسيقى الليل', 'Arabic title.', 0, 'audio', '["arabic"]', 18, true),
256 (proj_id, 'Ночная музыка', 'Russian title.', 0, 'audio', '["russian"]', 19, true),
257 (proj_id, 'Track with Emoji 🎵🎶', 'Emoji in title.', 0, 'audio', '["emoji"]', 20, true),
258 (proj_id, 'Ümläuts & Äccénts', 'European characters.', 0, 'audio', '["european"]', 21, true);
259
260 -- Very long description (text items can have body content)
261 INSERT INTO items (project_id, title, description, price_cents, item_type, tags, sort_order, is_public) VALUES
262 (proj_id, 'Long Description Item',
263 'This item has an extremely long description. ' ||
264 repeat('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ', 100),
265 0, 'text', '["long"]', 22, true);
266
267 -- Empty/null edge cases
268 INSERT INTO items (project_id, title, description, price_cents, item_type, tags, sort_order, is_public) VALUES
269 (proj_id, 'No Description', NULL, 0, 'audio', '[]', 23, true),
270 (proj_id, 'Empty Description', '', 0, 'audio', '[]', 24, true),
271 (proj_id, 'Empty Tags', 'Has no tags.', 0, 'audio', '[]', 25, true),
272 (proj_id, 'Whitespace Desc', ' ', 0, 'audio', '[]', 26, true);
273
274 -- Special characters in titles
275 INSERT INTO items (project_id, title, description, price_cents, item_type, tags, sort_order, is_public) VALUES
276 (proj_id, 'Track with "Quotes"', 'Double quotes in title.', 0, 'audio', '[]', 27, true),
277 (proj_id, E'Track with \'Apostrophe\'', 'Single quotes.', 0, 'audio', '[]', 28, true),
278 (proj_id, 'Track & Ampersand', 'Ampersand in title.', 0, 'audio', '[]', 29, true),
279 (proj_id, 'Track <Brackets>', 'Angle brackets.', 0, 'audio', '[]', 30, true),
280 (proj_id, 'Back\slash Track', 'Backslash.', 0, 'audio', '[]', 31, true),
281 (proj_id, 'Percent%Track', 'Percent sign.', 0, 'audio', '[]', 32, true);
282
283 END $$;
284
285 -- =============================================================================
286 -- MORE PROJECTS/ITEMS FOR PAGINATION
287 -- =============================================================================
288
289 -- Create more users and projects to ensure pagination is tested
290 DO $$
291 DECLARE
292 i INTEGER;
293 user_id UUID;
294 BEGIN
295 FOR i IN 1..30 LOOP
296 INSERT INTO users (username, email, password_hash, display_name, bio)
297 VALUES (
298 'paginationuser' || i,
299 'pagination' || i || '@test.com',
300 '$argon2id$v=19$m=19456,t=2,p=1$DKKe+bI4TwiyxkLgyCDZMA$oXVcdLHZIxv1hkFGK4JB5HNqoGURavSXhY9gjmvQeEM',
301 'Pagination User ' || i,
302 'User created for pagination testing.'
303 ) RETURNING id INTO user_id;
304
305 -- Create 2 projects per user
306 INSERT INTO projects (user_id, slug, title, description, project_type, is_public)
307 VALUES
308 (user_id, 'project-a', 'Project A by User ' || i, 'First project.', 'music', true),
309 (user_id, 'project-b', 'Project B by User ' || i, 'Second project.', 'podcast', true);
310
311 -- Create 3 items per first project
312 INSERT INTO items (project_id, title, description, price_cents, item_type, tags, is_public)
313 SELECT
314 p.id,
315 'Item ' || item_num || ' of Project A',
316 'Item description.',
317 item_num * 100,
318 'audio',
319 '["pagination", "test"]',
320 true
321 FROM projects p, generate_series(1, 3) AS item_num
322 WHERE p.user_id = user_id AND p.slug = 'project-a';
323 END LOOP;
324 END $$;
325
326 -- =============================================================================
327 -- CUSTOM LINKS - Edge cases
328 -- =============================================================================
329
330 DO $$
331 DECLARE
332 xss1_id UUID;
333 BEGIN
334 SELECT id INTO xss1_id FROM users WHERE username = 'xss1';
335
336 INSERT INTO custom_links (user_id, url, title, description, sort_order) VALUES
337 (xss1_id, 'https://example.com', '<script>alert(1)</script>', 'XSS in link title.', 1),
338 (xss1_id, 'javascript:alert(1)', 'JavaScript URL', 'JS protocol in URL.', 2),
339 (xss1_id, 'https://example.com', 'Normal Title', '<img src=x onerror=alert(1)>', 3),
340 (xss1_id, 'data:text/html,<script>alert(1)</script>', 'Data URL', 'Data protocol.', 4);
341 END $$;
342
343 -- =============================================================================
344 -- SUMMARY
345 -- =============================================================================
346
347 SELECT 'Users created: ' || COUNT(*) FROM users;
348 SELECT 'Projects created: ' || COUNT(*) FROM projects;
349 SELECT 'Items created: ' || COUNT(*) FROM items;
350 SELECT 'Custom links created: ' || COUNT(*) FROM custom_links;
351