Fossil SCM

Transform the forum status setting into a temp table to more easily filter on it.

stephan 2026-05-25 18:13 UTC forum-statuses
Commit 5e5edbe5b3a8c5d93f5539f5e621faa45c088e7cde0d6f53185a411b63dee5d0
1 file changed +68 -5
+68 -5
--- src/forum.c
+++ src/forum.c
@@ -66,12 +66,12 @@
6666
6767
/*
6868
** A single entry from the forum-statuses setting.
6969
*/
7070
struct ForumStatus {
71
- char *zValue; /* status=X tag value */
7271
char *zLabel; /* Label for the UI */
72
+ char *zValue; /* status=X tag value */
7373
char *zDescr; /* Brief description */
7474
};
7575
7676
/*
7777
** A list of ForumStatus objects.
@@ -87,21 +87,67 @@
8787
** This is a singleton, cached across calls.
8888
*/
8989
static const ForumStatusList * forum_statuses(void){
9090
static ForumStatusList fses = {0,0};
9191
static int once = 0;
92
- if( !once ){
92
+ while( !once ){
93
+ Stmt q;
94
+ char *zSetting;
9395
++once;
94
- /* TODO: read `forum-statuses` setting and transform it into the
96
+ /* Read `forum-statuses` setting and transform it into the
9597
** fses object.
9698
**
9799
** Maybe: if it's empty, synthesize a length-1 list from
98100
** {value:"default",label:"Default",...}. It's expected that
99101
** usage may be slightly simplified if we always have a non-empty
100102
** list. A length-1 list is, for purposes of the UI, identical to
101
- ** an empty one - we cannot change statuses if there's only one
102
- ** choice. */
103
+ ** an empty one - status selection/filtering makes no sense if
104
+ ** there's only one choice. */
105
+ zSetting = db_get("forum-statuses", 0);
106
+ db_multi_exec(
107
+ "CREATE TEMP TABLE forumstatus("
108
+ " ord, label, value, descr"
109
+ ");"
110
+ );
111
+ if( !zSetting ) break;
112
+ db_prepare(&q,
113
+ " WITH setting(v) AS (SELECT %Q),"
114
+ " room(r) AS ("
115
+ " SELECT e.value FROM setting s, jsonb_each(s.v) e"
116
+ " WHERE json_valid(s.v, 0x02)"
117
+ " )"
118
+ " SELECT r->>'label', r->>'value', r->>'description'"
119
+ " FROM room",
120
+ zSetting
121
+ );
122
+ while( SQLITE_ROW==db_step(&q) ){
123
+ ++fses.n;
124
+ }
125
+ if( fses.n ){
126
+ unsigned int i = 0;
127
+ Stmt qIns;
128
+ fses.aStatus = fossil_malloc(sizeof(fses.aStatus[0]) * fses.n);
129
+ db_reset(&q);
130
+ db_prepare(&qIns,
131
+ "INSERT INTO forumstatus(ord,label,value,descr)"
132
+ " VALUES(:ord,:label,:value,:descr)");
133
+ while( SQLITE_ROW==db_step(&q) ){
134
+ ForumStatus * fs = &fses.aStatus[i++];
135
+ fs->zLabel = fossil_strdup(db_column_text(&q, 0));
136
+ fs->zValue = fossil_strdup(db_column_text(&q, 1));
137
+ fs->zDescr = fossil_strdup(db_column_text(&q, 2));
138
+ db_reset(&qIns);
139
+ db_bind_int(&qIns, ":ord", (int)i);
140
+ db_bind_text(&qIns, ":label", fs->zLabel);
141
+ db_bind_text(&qIns, ":value", fs->zValue);
142
+ db_bind_text(&qIns, ":descr", fs->zDescr);
143
+ db_step(&qIns);
144
+ }
145
+ db_finalize(&qIns);
146
+ }
147
+ db_finalize(&q);
148
+ fossil_free(zSetting);
103149
}
104150
return &fses;
105151
}
106152
107153
/*
@@ -124,10 +170,27 @@
124170
fs0 = fs;
125171
}
126172
}
127173
return bFirst ? fs0 : 0;
128174
}
175
+
176
+/*
177
+** COMMAND: test-forum-statuses
178
+*/
179
+void test_forum_statuses_cmd(void){
180
+ const ForumStatusList * fses;
181
+ unsigned i;
182
+ db_find_and_open_repository(0,0);
183
+ fses = forum_statuses();
184
+ for(i = 0; i < fses->n; ++i ){
185
+ const ForumStatus * fs = &fses->aStatus[i];
186
+ fossil_print("Status: %!j %!j %!j\n",
187
+ fs->zValue, fs->zLabel, fs->zDescr);
188
+ assert( fs==forum_status_by_value(fs->zValue, 0) );
189
+ }
190
+ fossil_print("Total statuses: %u\n", i);
191
+}
129192
130193
/*
131194
** Return true if the forum post with the given rid has been
132195
** subsequently edited.
133196
*/
134197
--- src/forum.c
+++ src/forum.c
@@ -66,12 +66,12 @@
66
67 /*
68 ** A single entry from the forum-statuses setting.
69 */
70 struct ForumStatus {
71 char *zValue; /* status=X tag value */
72 char *zLabel; /* Label for the UI */
 
73 char *zDescr; /* Brief description */
74 };
75
76 /*
77 ** A list of ForumStatus objects.
@@ -87,21 +87,67 @@
87 ** This is a singleton, cached across calls.
88 */
89 static const ForumStatusList * forum_statuses(void){
90 static ForumStatusList fses = {0,0};
91 static int once = 0;
92 if( !once ){
 
 
93 ++once;
94 /* TODO: read `forum-statuses` setting and transform it into the
95 ** fses object.
96 **
97 ** Maybe: if it's empty, synthesize a length-1 list from
98 ** {value:"default",label:"Default",...}. It's expected that
99 ** usage may be slightly simplified if we always have a non-empty
100 ** list. A length-1 list is, for purposes of the UI, identical to
101 ** an empty one - we cannot change statuses if there's only one
102 ** choice. */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103 }
104 return &fses;
105 }
106
107 /*
@@ -124,10 +170,27 @@
124 fs0 = fs;
125 }
126 }
127 return bFirst ? fs0 : 0;
128 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
130 /*
131 ** Return true if the forum post with the given rid has been
132 ** subsequently edited.
133 */
134
--- src/forum.c
+++ src/forum.c
@@ -66,12 +66,12 @@
66
67 /*
68 ** A single entry from the forum-statuses setting.
69 */
70 struct ForumStatus {
 
71 char *zLabel; /* Label for the UI */
72 char *zValue; /* status=X tag value */
73 char *zDescr; /* Brief description */
74 };
75
76 /*
77 ** A list of ForumStatus objects.
@@ -87,21 +87,67 @@
87 ** This is a singleton, cached across calls.
88 */
89 static const ForumStatusList * forum_statuses(void){
90 static ForumStatusList fses = {0,0};
91 static int once = 0;
92 while( !once ){
93 Stmt q;
94 char *zSetting;
95 ++once;
96 /* Read `forum-statuses` setting and transform it into the
97 ** fses object.
98 **
99 ** Maybe: if it's empty, synthesize a length-1 list from
100 ** {value:"default",label:"Default",...}. It's expected that
101 ** usage may be slightly simplified if we always have a non-empty
102 ** list. A length-1 list is, for purposes of the UI, identical to
103 ** an empty one - status selection/filtering makes no sense if
104 ** there's only one choice. */
105 zSetting = db_get("forum-statuses", 0);
106 db_multi_exec(
107 "CREATE TEMP TABLE forumstatus("
108 " ord, label, value, descr"
109 ");"
110 );
111 if( !zSetting ) break;
112 db_prepare(&q,
113 " WITH setting(v) AS (SELECT %Q),"
114 " room(r) AS ("
115 " SELECT e.value FROM setting s, jsonb_each(s.v) e"
116 " WHERE json_valid(s.v, 0x02)"
117 " )"
118 " SELECT r->>'label', r->>'value', r->>'description'"
119 " FROM room",
120 zSetting
121 );
122 while( SQLITE_ROW==db_step(&q) ){
123 ++fses.n;
124 }
125 if( fses.n ){
126 unsigned int i = 0;
127 Stmt qIns;
128 fses.aStatus = fossil_malloc(sizeof(fses.aStatus[0]) * fses.n);
129 db_reset(&q);
130 db_prepare(&qIns,
131 "INSERT INTO forumstatus(ord,label,value,descr)"
132 " VALUES(:ord,:label,:value,:descr)");
133 while( SQLITE_ROW==db_step(&q) ){
134 ForumStatus * fs = &fses.aStatus[i++];
135 fs->zLabel = fossil_strdup(db_column_text(&q, 0));
136 fs->zValue = fossil_strdup(db_column_text(&q, 1));
137 fs->zDescr = fossil_strdup(db_column_text(&q, 2));
138 db_reset(&qIns);
139 db_bind_int(&qIns, ":ord", (int)i);
140 db_bind_text(&qIns, ":label", fs->zLabel);
141 db_bind_text(&qIns, ":value", fs->zValue);
142 db_bind_text(&qIns, ":descr", fs->zDescr);
143 db_step(&qIns);
144 }
145 db_finalize(&qIns);
146 }
147 db_finalize(&q);
148 fossil_free(zSetting);
149 }
150 return &fses;
151 }
152
153 /*
@@ -124,10 +170,27 @@
170 fs0 = fs;
171 }
172 }
173 return bFirst ? fs0 : 0;
174 }
175
176 /*
177 ** COMMAND: test-forum-statuses
178 */
179 void test_forum_statuses_cmd(void){
180 const ForumStatusList * fses;
181 unsigned i;
182 db_find_and_open_repository(0,0);
183 fses = forum_statuses();
184 for(i = 0; i < fses->n; ++i ){
185 const ForumStatus * fs = &fses->aStatus[i];
186 fossil_print("Status: %!j %!j %!j\n",
187 fs->zValue, fs->zLabel, fs->zDescr);
188 assert( fs==forum_status_by_value(fs->zValue, 0) );
189 }
190 fossil_print("Total statuses: %u\n", i);
191 }
192
193 /*
194 ** Return true if the forum post with the given rid has been
195 ** subsequently edited.
196 */
197

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button