Mercurial > paster
annotate database.c @ 85:478d96a4b039 default tip @
pasterd: use a thread as more portable
author | David Demelier <markand@malikania.fr> |
---|---|
date | Fri, 17 Mar 2023 11:43:36 +0100 |
parents | 94dcca86e5cc |
children |
rev | line source |
---|---|
6
98ef2713eb0d
pasterd: add licenses in database
David Demelier <markand@malikania.fr>
parents:
5
diff
changeset
|
1 /* |
98ef2713eb0d
pasterd: add licenses in database
David Demelier <markand@malikania.fr>
parents:
5
diff
changeset
|
2 * database.c -- sqlite storage |
98ef2713eb0d
pasterd: add licenses in database
David Demelier <markand@malikania.fr>
parents:
5
diff
changeset
|
3 * |
72
1a98bc0daa49
misc: update copyright years
David Demelier <markand@malikania.fr>
parents:
60
diff
changeset
|
4 * Copyright (c) 2020-2023 David Demelier <markand@malikania.fr> |
6
98ef2713eb0d
pasterd: add licenses in database
David Demelier <markand@malikania.fr>
parents:
5
diff
changeset
|
5 * |
98ef2713eb0d
pasterd: add licenses in database
David Demelier <markand@malikania.fr>
parents:
5
diff
changeset
|
6 * Permission to use, copy, modify, and/or distribute this software for any |
98ef2713eb0d
pasterd: add licenses in database
David Demelier <markand@malikania.fr>
parents:
5
diff
changeset
|
7 * purpose with or without fee is hereby granted, provided that the above |
98ef2713eb0d
pasterd: add licenses in database
David Demelier <markand@malikania.fr>
parents:
5
diff
changeset
|
8 * copyright notice and this permission notice appear in all copies. |
98ef2713eb0d
pasterd: add licenses in database
David Demelier <markand@malikania.fr>
parents:
5
diff
changeset
|
9 * |
98ef2713eb0d
pasterd: add licenses in database
David Demelier <markand@malikania.fr>
parents:
5
diff
changeset
|
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
98ef2713eb0d
pasterd: add licenses in database
David Demelier <markand@malikania.fr>
parents:
5
diff
changeset
|
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
98ef2713eb0d
pasterd: add licenses in database
David Demelier <markand@malikania.fr>
parents:
5
diff
changeset
|
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
98ef2713eb0d
pasterd: add licenses in database
David Demelier <markand@malikania.fr>
parents:
5
diff
changeset
|
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
98ef2713eb0d
pasterd: add licenses in database
David Demelier <markand@malikania.fr>
parents:
5
diff
changeset
|
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
98ef2713eb0d
pasterd: add licenses in database
David Demelier <markand@malikania.fr>
parents:
5
diff
changeset
|
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
98ef2713eb0d
pasterd: add licenses in database
David Demelier <markand@malikania.fr>
parents:
5
diff
changeset
|
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
98ef2713eb0d
pasterd: add licenses in database
David Demelier <markand@malikania.fr>
parents:
5
diff
changeset
|
17 */ |
98ef2713eb0d
pasterd: add licenses in database
David Demelier <markand@malikania.fr>
parents:
5
diff
changeset
|
18 |
0 | 19 #include <assert.h> |
20 #include <stdlib.h> | |
21 #include <stdio.h> | |
22 #include <string.h> | |
23 | |
24 #include <sqlite3.h> | |
25 | |
26 #include "database.h" | |
27 #include "log.h" | |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
28 #include "paste.h" |
0 | 29 #include "util.h" |
30 | |
78
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
31 #include "sql/clear.h" |
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
32 #include "sql/get.h" |
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
33 #include "sql/init.h" |
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
34 #include "sql/insert.h" |
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
35 #include "sql/recents.h" |
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
36 #include "sql/search.h" |
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
37 |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
38 #define CHAR(sql) (const char *)(sql) |
78
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
39 |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
40 static char * |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
41 dup(const unsigned char *s) |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
42 { |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
43 return estrdup(s ? (const char *)(s) : ""); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
44 } |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
45 |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
46 static void |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
47 convert(sqlite3_stmt *stmt, struct paste *paste) |
1
836a698946f8
pasterd: add basic routes
David Demelier <markand@malikania.fr>
parents:
0
diff
changeset
|
48 { |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
49 paste->id = dup(sqlite3_column_text(stmt, 0)); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
50 paste->title = dup(sqlite3_column_text(stmt, 1)); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
51 paste->author = dup(sqlite3_column_text(stmt, 2)); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
52 paste->language = dup(sqlite3_column_text(stmt, 3)); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
53 paste->code = dup(sqlite3_column_text(stmt, 4)); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
54 paste->timestamp = sqlite3_column_int64(stmt, 5); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
55 paste->visible = sqlite3_column_int(stmt, 6); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
56 paste->duration = sqlite3_column_int64(stmt, 7); |
1
836a698946f8
pasterd: add basic routes
David Demelier <markand@malikania.fr>
parents:
0
diff
changeset
|
57 } |
836a698946f8
pasterd: add basic routes
David Demelier <markand@malikania.fr>
parents:
0
diff
changeset
|
58 |
78
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
59 static int |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
60 exists(struct database *db, const char *id) |
38
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
61 { |
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
62 assert(id); |
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
63 |
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
64 sqlite3_stmt *stmt = NULL; |
78
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
65 int ret = 1; |
38
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
66 |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
67 if (sqlite3_prepare(db->handle, CHAR(sql_get), -1, &stmt, NULL) == SQLITE_OK) { |
44
f939d7864de4
pasterd: fix unique key constraint
David Demelier <markand@malikania.fr>
parents:
43
diff
changeset
|
68 sqlite3_bind_text(stmt, 1, id, -1, NULL); |
f939d7864de4
pasterd: fix unique key constraint
David Demelier <markand@malikania.fr>
parents:
43
diff
changeset
|
69 ret = sqlite3_step(stmt) == SQLITE_ROW; |
f939d7864de4
pasterd: fix unique key constraint
David Demelier <markand@malikania.fr>
parents:
43
diff
changeset
|
70 sqlite3_finalize(stmt); |
38
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
71 } |
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
72 |
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
73 return ret; |
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
74 } |
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
75 |
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
76 static const char * |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
77 create_id(void) |
38
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
78 { |
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
79 static const char table[] = "abcdefghijklmnopqrstuvwxyz1234567890"; |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
80 static char id[12]; |
38
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
81 |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
82 for (size_t i = 0; i < sizeof (id); ++i) |
43
a2789cb8ebe6
pasterd: avoid creating null identifiers
David Demelier <markand@malikania.fr>
parents:
42
diff
changeset
|
83 id[i] = table[rand() % (sizeof (table) - 1)]; |
38
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
84 |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
85 return id; |
38
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
86 } |
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
87 |
78
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
88 static int |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
89 set_id(struct database *db, struct paste *paste) |
38
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
90 { |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
91 assert(paste); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
92 |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
93 paste->id = NULL; |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
94 |
38
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
95 /* |
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
96 * Avoid infinite loop, we only try to create a new id in 30 steps. |
44
f939d7864de4
pasterd: fix unique key constraint
David Demelier <markand@malikania.fr>
parents:
43
diff
changeset
|
97 * |
f939d7864de4
pasterd: fix unique key constraint
David Demelier <markand@malikania.fr>
parents:
43
diff
changeset
|
98 * On error, the function `exist` returns true to indicate we should |
f939d7864de4
pasterd: fix unique key constraint
David Demelier <markand@malikania.fr>
parents:
43
diff
changeset
|
99 * not try to save with that id. |
38
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
100 */ |
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
101 int tries = 0; |
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
102 |
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
103 do { |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
104 free(paste->id); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
105 paste->id = estrdup(create_id()); |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
106 } while (++tries < 30 && exists(db, paste->id)); |
38
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
107 |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
108 return tries < 30 ? 0 : -1; |
38
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
109 } |
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
110 |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
111 struct database database; |
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
112 |
78
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
113 int |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
114 database_open(struct database *db, const char *path) |
0 | 115 { |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
116 assert(db); |
0 | 117 assert(path); |
118 | |
21
21c103c33ac9
pasterd: improve verbosity, closes #2472
David Demelier <markand@malikania.fr>
parents:
6
diff
changeset
|
119 log_info("database: opening %s", path); |
0 | 120 |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
121 if (sqlite3_open(path, (sqlite3 **)&db->handle) != SQLITE_OK) { |
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
122 log_warn("database: unable to open %s: %s", path, sqlite3_errmsg(db->handle)); |
78
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
123 return -1; |
0 | 124 } |
125 | |
30
4f60cf394839
pasterd: enable lock timeout
David Demelier <markand@malikania.fr>
parents:
25
diff
changeset
|
126 /* Wait for 30 seconds to lock the database. */ |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
127 sqlite3_busy_timeout(db->handle, 30000); |
30
4f60cf394839
pasterd: enable lock timeout
David Demelier <markand@malikania.fr>
parents:
25
diff
changeset
|
128 |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
129 if (sqlite3_exec(db->handle, CHAR(sql_init), NULL, NULL, NULL) != SQLITE_OK) { |
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
130 log_warn("database: unable to initialize %s: %s", path, sqlite3_errmsg(db->handle)); |
78
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
131 return -1; |
0 | 132 } |
133 | |
78
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
134 return 0; |
0 | 135 } |
136 | |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
137 int |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
138 database_recents(struct database *db, struct paste *pastes, size_t *max) |
0 | 139 { |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
140 assert(db); |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
141 assert(pastes); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
142 assert(max); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
143 |
78
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
144 sqlite3_stmt *stmt = NULL; |
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
145 size_t i = 0; |
0 | 146 |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
147 memset(pastes, 0, *max * sizeof (struct paste)); |
21
21c103c33ac9
pasterd: improve verbosity, closes #2472
David Demelier <markand@malikania.fr>
parents:
6
diff
changeset
|
148 log_debug("database: accessing most recents"); |
0 | 149 |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
150 if (sqlite3_prepare(db->handle, CHAR(sql_recents), -1, &stmt, NULL) != SQLITE_OK || |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
151 sqlite3_bind_int64(stmt, 1, *max) != SQLITE_OK) |
0 | 152 goto sqlite_err; |
153 | |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
154 for (; i < *max && sqlite3_step(stmt) == SQLITE_ROW; ++i) |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
155 convert(stmt, &pastes[i]); |
0 | 156 |
21
21c103c33ac9
pasterd: improve verbosity, closes #2472
David Demelier <markand@malikania.fr>
parents:
6
diff
changeset
|
157 log_debug("database: found %zu pastes", i); |
0 | 158 sqlite3_finalize(stmt); |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
159 *max = i; |
0 | 160 |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
161 return 0; |
0 | 162 |
163 sqlite_err: | |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
164 log_warn("database: error (recents): %s\n", sqlite3_errmsg(db->handle)); |
0 | 165 |
166 if (stmt) | |
167 sqlite3_finalize(stmt); | |
168 | |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
169 *max = 0; |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
170 |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
171 return -1; |
0 | 172 } |
173 | |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
174 int |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
175 database_get(struct database *db, struct paste *paste, const char *id) |
0 | 176 { |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
177 assert(db); |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
178 assert(paste); |
78
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
179 assert(id); |
0 | 180 |
42
62361336c415
pasterd: return false when we don't find a paste
David Demelier <markand@malikania.fr>
parents:
38
diff
changeset
|
181 sqlite3_stmt* stmt = NULL; |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
182 int found = -1; |
42
62361336c415
pasterd: return false when we don't find a paste
David Demelier <markand@malikania.fr>
parents:
38
diff
changeset
|
183 |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
184 memset(paste, 0, sizeof (struct paste)); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
185 log_debug("database: accessing paste with id: %s", id); |
0 | 186 |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
187 if (sqlite3_prepare(db->handle, CHAR(sql_get), -1, &stmt, NULL) != SQLITE_OK || |
78
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
188 sqlite3_bind_text(stmt, 1, id, -1, NULL) != SQLITE_OK) |
0 | 189 goto sqlite_err; |
190 | |
191 switch (sqlite3_step(stmt)) { | |
192 case SQLITE_ROW: | |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
193 convert(stmt, paste); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
194 found = 0; |
0 | 195 break; |
196 case SQLITE_MISUSE: | |
197 case SQLITE_ERROR: | |
198 goto sqlite_err; | |
199 default: | |
200 break; | |
201 } | |
202 | |
203 sqlite3_finalize(stmt); | |
204 | |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
205 return found; |
0 | 206 |
207 sqlite_err: | |
208 if (stmt) | |
209 sqlite3_finalize(stmt); | |
210 | |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
211 log_warn("database: error (get): %s", sqlite3_errmsg(db->handle)); |
0 | 212 |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
213 return -1; |
0 | 214 } |
215 | |
78
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
216 int |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
217 database_insert(struct database *db, struct paste *paste) |
0 | 218 { |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
219 assert(db); |
0 | 220 assert(paste); |
221 | |
38
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
222 sqlite3_stmt *stmt = NULL; |
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
223 |
21
21c103c33ac9
pasterd: improve verbosity, closes #2472
David Demelier <markand@malikania.fr>
parents:
6
diff
changeset
|
224 log_debug("database: creating new paste"); |
0 | 225 |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
226 if (sqlite3_exec(db->handle, "BEGIN EXCLUSIVE TRANSACTION", NULL, NULL, NULL) != SQLITE_OK) { |
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
227 log_warn("database: could not lock database: %s", sqlite3_errmsg(db->handle)); |
78
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
228 return -1; |
0 | 229 } |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
230 if (set_id(db, paste) < 0) { |
38
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
231 log_warn("database: unable to randomize unique identifier"); |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
232 sqlite3_exec(db->handle, "END TRANSACTION", NULL, NULL, NULL); |
78
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
233 return -1; |
38
48834441dc86
pasterd: generate smaller identifiers, closes #2480 @1h
David Demelier <markand@malikania.fr>
parents:
30
diff
changeset
|
234 } |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
235 if (sqlite3_prepare(db->handle, CHAR(sql_insert), -1, &stmt, NULL) != SQLITE_OK) |
0 | 236 goto sqlite_err; |
237 | |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
238 sqlite3_bind_text(stmt, 1, paste->id, -1, SQLITE_STATIC); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
239 sqlite3_bind_text(stmt, 2, paste->title, -1, SQLITE_STATIC); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
240 sqlite3_bind_text(stmt, 3, paste->author, -1, SQLITE_STATIC); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
241 sqlite3_bind_text(stmt, 4, paste->language, -1, SQLITE_STATIC); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
242 sqlite3_bind_text(stmt, 5, paste->code, -1, SQLITE_STATIC); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
243 sqlite3_bind_int(stmt, 6, paste->visible); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
244 sqlite3_bind_int64(stmt, 7, paste->duration); |
0 | 245 |
246 if (sqlite3_step(stmt) != SQLITE_DONE) | |
247 goto sqlite_err; | |
248 | |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
249 sqlite3_exec(db->handle, "COMMIT", NULL, NULL, NULL); |
0 | 250 sqlite3_finalize(stmt); |
251 | |
21
21c103c33ac9
pasterd: improve verbosity, closes #2472
David Demelier <markand@malikania.fr>
parents:
6
diff
changeset
|
252 log_info("database: new paste (%s) from %s expires in one %lld seconds", |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
253 paste->id, paste->author, paste->duration); |
0 | 254 |
78
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
255 return 0; |
0 | 256 |
257 sqlite_err: | |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
258 log_warn("database: error (insert): %s", sqlite3_errmsg(db->handle)); |
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
259 sqlite3_exec(db->handle, "ROLLBACK", NULL, NULL, NULL); |
0 | 260 |
261 if (stmt) | |
262 sqlite3_finalize(stmt); | |
263 | |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
264 free(paste->id); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
265 paste->id = NULL; |
0 | 266 |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
267 return -1; |
0 | 268 } |
269 | |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
270 int |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
271 database_search(struct database *db, |
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
272 struct paste *pastes, |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
273 size_t *max, |
25
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
274 const char *title, |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
275 const char *author, |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
276 const char *language) |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
277 { |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
278 assert(db); |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
279 assert(pastes); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
280 assert(max); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
281 |
25
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
282 sqlite3_stmt *stmt = NULL; |
78
9bfe5ce3cc45
pasterd: rework themes
David Demelier <markand@malikania.fr>
parents:
72
diff
changeset
|
283 size_t i = 0; |
25
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
284 |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
285 log_debug("database: searching title=%s, author=%s, language=%s", |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
286 title ? title : "", |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
287 author ? author : "", |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
288 language ? language : ""); |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
289 |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
290 memset(pastes, 0, *max * sizeof (struct paste)); |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
291 |
25
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
292 /* Select everything if not specified. */ |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
293 title = title ? title : "%"; |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
294 author = author ? author : "%"; |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
295 language = language ? language : "%"; |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
296 |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
297 if (sqlite3_prepare(db->handle, CHAR(sql_search), -1, &stmt, NULL) != SQLITE_OK) |
25
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
298 goto sqlite_err; |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
299 if (sqlite3_bind_text(stmt, 1, title, -1, NULL) != SQLITE_OK) |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
300 goto sqlite_err; |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
301 if (sqlite3_bind_text(stmt, 2, author, -1, NULL) != SQLITE_OK) |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
302 goto sqlite_err; |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
303 if (sqlite3_bind_text(stmt, 3, language, -1, NULL) != SQLITE_OK) |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
304 goto sqlite_err; |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
305 if (sqlite3_bind_int64(stmt, 4, *max) != SQLITE_OK) |
25
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
306 goto sqlite_err; |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
307 |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
308 for (; i < *max && sqlite3_step(stmt) == SQLITE_ROW; ++i) |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
309 convert(stmt, &pastes[i]); |
25
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
310 |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
311 log_debug("database: found %zu pastes", i); |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
312 sqlite3_finalize(stmt); |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
313 *max = i; |
25
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
314 |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
315 return 0; |
25
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
316 |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
317 sqlite_err: |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
318 log_warn("database: error (search): %s\n", sqlite3_errmsg(db->handle)); |
25
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
319 |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
320 if (stmt) |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
321 sqlite3_finalize(stmt); |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
322 |
79
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
323 *max = 0; |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
324 |
52029a52a385
pasterd: revert using ktemplate
David Demelier <markand@malikania.fr>
parents:
78
diff
changeset
|
325 return -1; |
25
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
326 } |
f4e8a7920b94
pasterd: implement search, closes #2474 @30m
David Demelier <markand@malikania.fr>
parents:
21
diff
changeset
|
327 |
0 | 328 void |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
329 database_clear(struct database *db) |
0 | 330 { |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
331 assert(db); |
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
332 |
21
21c103c33ac9
pasterd: improve verbosity, closes #2472
David Demelier <markand@malikania.fr>
parents:
6
diff
changeset
|
333 log_debug("database: clearing deprecated pastes"); |
21c103c33ac9
pasterd: improve verbosity, closes #2472
David Demelier <markand@malikania.fr>
parents:
6
diff
changeset
|
334 |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
335 if (sqlite3_exec(db->handle, CHAR(sql_clear), NULL, NULL, NULL) != SQLITE_OK) |
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
336 log_warn("database: error (clear): %s\n", sqlite3_errmsg(db->handle)); |
0 | 337 } |
338 | |
339 void | |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
340 database_finish(struct database *db) |
0 | 341 { |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
342 assert(db); |
21
21c103c33ac9
pasterd: improve verbosity, closes #2472
David Demelier <markand@malikania.fr>
parents:
6
diff
changeset
|
343 |
84
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
344 log_debug("database: closing"); |
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
345 sqlite3_close(db->handle); |
94dcca86e5cc
pasterd: database reentrancy + timer
David Demelier <markand@malikania.fr>
parents:
79
diff
changeset
|
346 db->handle = NULL; |
0 | 347 } |