Differences From
Artifact [0f1425913d]:
131 131 select relatee as user from parsav_rels
132 132 where relator = $1::bigint and kind = <follow>
133 133 ),
134 134 followers as (
135 135 select relator as user from parsav_rels
136 136 where relatee = $1::bigint and kind = <follow>
137 137 ),
138 - mutuals as (select * from follows intersect select * from followers)
138 + mutuals as (
139 + select * from follows intersect select * from followers
140 + )
139 141
140 - select count(tweets.*)::bigint,
141 - count(follows.*)::bigint,
142 - count(followers.*)::bigint,
143 - count(mutuals.*)::bigint
144 - from tweets, follows, followers, mutuals
142 + values (
143 + (select count(tweets.*)::bigint from tweets),
144 + (select count(follows.*)::bigint from follows),
145 + (select count(followers.*)::bigint from followers),
146 + (select count(mutuals.*)::bigint from mutuals)
147 + )
145 148 ]]):gsub('<(%w+)>',function(r) return tostring(lib.store.relation[r]) end)
146 149 };
147 150
148 151 actor_auth_how = {
149 152 params = {rawstring, lib.store.inet}, sql = [[
150 153 with mts as (select a.kind from parsav_auth as a
151 154 left join parsav_actors as u on u.id = a.uid
................................................................................
278 281 (a.origin is null)
279 282 order by (p.posted, p.discovered) desc
280 283 limit case when $3::bigint = 0 then null
281 284 else $3::bigint end
282 285 offset $4::bigint
283 286 ]]
284 287 };
288 +
289 + artifact_instantiate = {
290 + params = {binblob, binblob, pstring}, sql = [[
291 + insert into parsav_artifacts (content,hash,mime) values (
292 + $1::bytea, $2::bytea, $3::text
293 + ) on conflict do nothing returning id
294 + ]];
295 + };
296 + artifact_expropriate = {
297 + params = {uint64, uint64, pstring}, cmd = true, sql = [[
298 + insert into parsav_artifact_claims (uid,rid,description,folder) values (
299 + $1::bigint, $2::bigint, $3::text, 'new'
300 + ) on conflict do nothing
301 + ]];
302 + };
303 + artifact_quicksearch = {
304 + params = {binblob}, sql = [[
305 + select id, (content is null) from parsav_artifacts where hash = $1::bytea
306 + limit 1
307 + ]];
308 + };
309 + artifact_disclaim = {
310 + params = {uint64, uint64}, cmd = true, sql = [[
311 + delete from parsav_artifact_claims where
312 + uid = $1::bigint and
313 + rid = $2::bigint
314 + ]];
315 + };
316 + artifact_excise_forget = {
317 + -- delete the blasted thing and pretend it never existed
318 + params = {uint64}, cmd=true, sql = [[
319 + delete from parsav_artifacts where id = $1::bigint
320 + ]];
321 + };
322 + artifact_excise_suppress_nullify = {
323 + -- banish the thing into the outer darkness, preventing
324 + -- it from ever being admitted into our databases, and
325 + -- tabulate a -- list of the degenerates who befouled
326 + -- their accounts with such wanton and execrable filth,
327 + -- the better to ensure their long-overdue punishment
328 + params = {uint64}, cmd=true, sql = [[
329 + update parsav_artifacts
330 + set content = null
331 + where id = $1::bigint;
332 + ]];
333 + };
334 + artifact_excise_suppress_breaklinks = {
335 + -- "ERROR: cannot insert multiple commands into a prepared
336 + -- statement" are you fucking shitting me with this shit
337 + params = {uint64}, sql = [[
338 + delete from parsav_artifact_claims where
339 + rid = $1::bigint
340 + returning uid, description, birth, folder;
341 + ]];
342 + };
343 + post_attach_ctl_ins = {
344 + params = {uint64, uint64}, cmd=true, sql = [[
345 + update parsav_posts set
346 + artifacts = artifacts || $2::bigint
347 + where id = $1::bigint and not
348 + artifacts @> array[$2::bigint]
349 + ]];
350 + };
351 + post_attach_ctl_del = {
352 + params = {uint64, uint64}, cmd=true, sql = [[
353 + update parsav_posts set
354 + artifacts = array_remove(artifacts, $2::bigint)
355 + where id = $1::bigint and
356 + artifacts @> array[$2::bigint]
357 + ]];
358 + };
285 359 }
286 - --($5::bool = false or p.parent is null) and
287 360
288 361 local struct pqr {
289 362 sz: intptr
290 363 res: &lib.pq.PGresult
291 364 }
292 365 terra pqr:free() if self.sz > 0 then lib.pq.PQclear(self.res) end end
293 366 terra pqr:null(row: intptr, col: intptr)
................................................................................
685 758 lib.report('successfully wiped out everything parsav-related in database')
686 759 return true
687 760 else
688 761 lib.warn('backend pgsql - failed to obliterate database: \n', lib.pq.PQresultErrorMessage(res))
689 762 return false
690 763 end
691 764 end];
765 +
766 + tx_enter = [terra(src: &lib.store.source)
767 + var res = lib.pq.PQexec([&lib.pq.PGconn](src.handle), 'begin')
768 + if lib.pq.PQresultStatus(res) == lib.pq.PGRES_COMMAND_OK then
769 + lib.dbg('beginning pgsql transaction')
770 + return true
771 + else
772 + lib.warn('backend pgsql - failed to begin transaction: \n', lib.pq.PQresultErrorMessage(res))
773 + return false
774 + end
775 + end];
776 +
777 + tx_complete = [terra(src: &lib.store.source)
778 + var res = lib.pq.PQexec([&lib.pq.PGconn](src.handle), 'end')
779 + if lib.pq.PQresultStatus(res) == lib.pq.PGRES_COMMAND_OK then
780 + lib.dbg('completing pgsql transaction')
781 + return true
782 + else
783 + lib.warn('backend pgsql - failed to complete transaction: \n', lib.pq.PQresultErrorMessage(res))
784 + return false
785 + end
786 + end];
692 787
693 788 conf_get = [terra(src: &lib.store.source, key: rawstring)
694 789 var r = queries.conf_get.exec(src, key)
695 790 if r.sz == 0 then return [lib.mem.ptr(int8)] { ptr = nil, ct = 0 } else
696 791 defer r:free()
697 792 return r:String(0,0)
698 793 end
................................................................................
905 1000 queries.auth_purge_type.exec(src, handle, uid, 'otp-%')
906 1001 end];
907 1002
908 1003 auth_purge_trust = [terra(src: &lib.store.source, uid: uint64, handle: rawstring): {}
909 1004 queries.auth_purge_type.exec(src, handle, uid, 'trust')
910 1005 end];
911 1006
912 - actor_auth_register_uid = nil; -- not necessary for view-based auth
1007 + artifact_quicksearch = [terra(
1008 + src: &lib.store.source,
1009 + hash: binblob
1010 + ): {uint64, bool}
1011 + var srec = queries.artifact_quicksearch.exec(src, hash)
1012 + if srec.sz > 0 then
1013 + defer srec:free()
1014 + var id = srec:int(uint64,0,0)
1015 + var ban = srec:bool(0,1)
1016 + return id, ban
1017 + else return 0, false end
1018 + end];
1019 +
1020 + artifact_instantiate = [terra(
1021 + src: &lib.store.source,
1022 + artifact: binblob,
1023 + mime: pstring
1024 + ): uint64
1025 + var arthash: uint8[lib.crypt.algsz.sha256]
1026 + if lib.md.mbedtls_md(lib.md.mbedtls_md_info_from_type(lib.crypt.alg.sha256.id),
1027 + artifact.ptr, artifact.ct, &arthash[0]) ~= 0 then
1028 + lib.bail('could not hash artifact to be instantiated')
1029 + end
1030 + var hashb = binblob{ptr=&arthash[0],ct=[arthash.type.N]}
1031 +
1032 + var srec = queries.artifact_quicksearch.exec(src, hashb)
1033 + if srec.sz > 0 then
1034 + defer srec:free()
1035 + var ban = srec:bool(0,1)
1036 + if ban then
1037 + lib.report('user attempted to instantiate forsaken artifact')
1038 + return 0
1039 + end
1040 + var oldid = srec:int(uint64,0,0)
1041 + return oldid
1042 + else -- not in db, insert
1043 + var nrec = queries.artifact_instantiate.exec(src, artifact, hashb, mime)
1044 + if nrec.sz == 0 then
1045 + lib.warn('failed to instantiate artifact -- are you running out of storage?')
1046 + return 0
1047 + else defer nrec:free()
1048 + var newid = nrec:int(uint64,0,0)
1049 + return newid
1050 + end
1051 + end
1052 + end];
1053 +
1054 + post_attach_ctl = [terra(
1055 + src: &lib.store.source,
1056 + post: uint64,
1057 + artifact: uint64,
1058 + detach: bool
1059 + ): {}
1060 + if detach
1061 + then queries.post_attach_ctl_del.exec(src,post,artifact)
1062 + else queries.post_attach_ctl_ins.exec(src,post,artifact)
1063 + end
1064 + end];
913 1065
1066 + actor_auth_register_uid = nil; -- TODO better support non-view based auth
914 1067 }
915 1068
916 1069 return b