Differences From
Artifact [18ea7fb9d0]:
457 457 where id = $1::bigint
458 458 ]]
459 459 };
460 460
461 461 post_create = {
462 462 params = {
463 463 uint64, rawstring, rawstring, rawstring,
464 - uint64, uint64, rawstring
464 + uint64, uint64, rawstring, rawstring
465 465 }, sql = [[
466 466 insert into parsav_posts (
467 467 author, subject, acl, body,
468 468 parent, posted, discovered,
469 - circles, mentions, convoheaduri
469 + circles, mentions, convoheaduri, uri
470 470 ) values (
471 471 $1::bigint, case when $2::text = '' then null else $2::text end,
472 472 $3::text, $4::text,
473 473 $5::bigint, $6::bigint, $6::bigint,
474 - array[]::bigint[], array[]::bigint[], $7::text
474 + array[]::bigint[], array[]::bigint[], $7::text, $8::text
475 475 ) returning id
476 476 ]]; -- TODO array handling
477 477 };
478 478
479 479 post_destroy_prepare = {
480 480 params = {uint64}, cmd = true, sql = [[
481 481 update parsav_posts set
................................................................................
502 502 params = {uint64}, sql = [[
503 503 select (p.post).*
504 504 from pg_temp.parsavpg_known_content as p
505 505 where (p.post).parent = $1::bigint and (p.post).rtdby = 0
506 506 order by (p.post).posted, (p.post).discovered asc
507 507 ]];
508 508 };
509 +
510 + thread_top_find = {
511 + params = {uint64}, sql = [[
512 + with recursive tree(gen,id,par) as (
513 + select 0, id, parent from parsav_posts where id = $1::bigint
514 + union
515 + select tree.gen + 1, p.id, p.parent from tree
516 + inner join parsav_posts as p on p.id = tree.par
517 + )
518 +
519 + select id from tree order by gen desc limit 1
520 + ]];
521 + };
509 522
510 523 thread_latest_arrival_calc = {
511 524 params = {uint64}, sql = [[
512 525 with recursive posts(id) as (
513 526 select id from parsav_posts where parent = $1::bigint
514 527 union
515 528 select p.id from parsav_posts as p
................................................................................
1022 1035 if ct == 0 then
1023 1036 lib.pq.PQclear(res)
1024 1037 return pqr {0, nil}
1025 1038 else
1026 1039 return pqr {ct, res}
1027 1040 end
1028 1041 end
1042 + q.exec.name = 'pgsql.' .. k .. '.exec'
1029 1043 end
1030 1044
1031 1045 local terra row_to_artifact(res: &pqr, i: intptr): lib.mem.ptr(lib.store.artifact)
1032 1046 var id = res:int(uint64,i,0)
1033 1047 var idbuf: int8[lib.math.shorthand.maxlen]
1034 1048 var idlen = lib.math.shorthand.gen(id, &idbuf[0])
1035 1049 var desc = res:_string(i,2)
................................................................................
1044 1058 m.ptr.rid = id
1045 1059 return m
1046 1060 end
1047 1061
1048 1062 local terra row_to_post(r: &pqr, row: intptr): lib.mem.ptr(lib.store.post)
1049 1063 var subj: rawstring, sblen: intptr
1050 1064 var cvhu: rawstring, cvhlen: intptr
1065 + var uri: rawstring, urilen: intptr
1051 1066 if r:null(row,3)
1052 1067 then subj = nil sblen = 0
1053 1068 else subj = r:string(row,3) sblen = r:len(row,3)+1
1054 1069 end
1055 1070 if r:null(row,10)
1056 1071 then cvhu = nil cvhlen = 0
1057 1072 else cvhu = r:string(row,10) cvhlen = r:len(row,10)+1
1058 1073 end
1074 + if r:null(row,12)
1075 + then uri = nil urilen = 0
1076 + else uri = r:string(row,12) urilen = r:len(row,12)+1
1077 + end
1059 1078 var p = [ lib.str.encapsulate(lib.store.post, {
1060 1079 subject = { `subj, `sblen };
1061 1080 acl = {`r:string(row,4), `r:len(row,4)+1};
1062 1081 body = {`r:string(row,5), `r:len(row,5)+1};
1063 1082 convoheaduri = { `cvhu, `cvhlen }; --FIXME
1083 + uri = { `uri, `urilen };
1064 1084 }) ]
1065 1085 p.ptr.id = r:int(uint64,row,1)
1066 1086 p.ptr.author = r:int(uint64,row,2)
1067 1087 if r:null(row,6)
1068 1088 then p.ptr.posted = 0
1069 1089 else p.ptr.posted = r:int(uint64,row,6)
1070 1090 end
................................................................................
1077 1097 else p.ptr.edited = r:int(uint64,row,8)
1078 1098 end
1079 1099 p.ptr.parent = r:int(uint64,row,9)
1080 1100 if r:null(row,11)
1081 1101 then p.ptr.chgcount = 0
1082 1102 else p.ptr.chgcount = r:int(uint32,row,11)
1083 1103 end
1084 - p.ptr.accent = r:int(int16,row,12)
1085 - p.ptr.rtdby = r:int(uint64,row,13)
1086 - p.ptr.rtdat = r:int(uint64,row,14)
1087 - p.ptr.rtact = r:int(uint64,row,15)
1088 - p.ptr.likes = r:int(uint32,row,16)
1089 - p.ptr.rts = r:int(uint32,row,17)
1090 - p.ptr.isreply = r:bool(row,18)
1104 + p.ptr.accent = r:int(int16,row,13)
1105 + p.ptr.rtdby = r:int(uint64,row,14)
1106 + p.ptr.rtdat = r:int(uint64,row,15)
1107 + p.ptr.rtact = r:int(uint64,row,16)
1108 + p.ptr.likes = r:int(uint32,row,17)
1109 + p.ptr.rts = r:int(uint32,row,18)
1110 + p.ptr.isreply = r:bool(row,19)
1091 1111 p.ptr.localpost = r:bool(row,0)
1092 1112
1093 1113 return p
1094 1114 end
1095 1115 local terra row_to_actor(r: &pqr, row: intptr): lib.mem.ptr(lib.store.actor)
1096 1116 var a: lib.mem.ptr(lib.store.actor)
1097 1117 var av: rawstring, avlen: intptr
1098 1118 var nym: rawstring, nymlen: intptr
1099 1119 var bio: rawstring, biolen: intptr
1100 1120 var epi: rawstring, epilen: intptr
1121 + var key: &uint8, keylen: intptr
1101 1122 var origin: uint64 = 0
1102 1123 var handle = r:_string(row, 2)
1103 1124 if not r:null(row,3) then origin = r:int(uint64,row,3) end
1104 1125
1105 1126 var avia = lib.str.acc {buf=nil}
1106 1127 if origin == 0 then
1107 1128 avia:compose('/avi/',handle)
................................................................................
1123 1144 bio = r:string(row,4)
1124 1145 biolen = r:len(row,4)+1
1125 1146 end
1126 1147 if r:null(row,9) then epilen = 0 epi = nil else
1127 1148 epi = r:string(row,9)
1128 1149 epilen = r:len(row,9)+1
1129 1150 end
1151 + if r:null(row,8) then
1152 + keylen = 0 key = nil
1153 + else
1154 + var k = r:bin(row,8)
1155 + keylen = k.ct key = k.ptr
1156 + end
1130 1157 a = [ lib.str.encapsulate(lib.store.actor, {
1131 1158 nym = {`nym, `nymlen};
1132 1159 bio = {`bio, `biolen};
1133 1160 epithet = {`epi, `epilen};
1134 1161 avatar = {`av,`avlen};
1135 1162 handle = {`handle.ptr, `handle.ct + 1};
1136 1163 xid = {`r:string(row, 11); `r:len(row,11) + 1};
1164 + key = {`key,`keylen};
1137 1165 }) ]
1138 1166 a.ptr.id = r:int(uint64, row, 0);
1139 1167 a.ptr.rights = lib.store.rights_default();
1140 1168 a.ptr.rights.rank = r:int(uint16, row, 6);
1141 1169 a.ptr.rights.quota = r:int(uint32, row, 7);
1142 1170 a.ptr.rights.invites = r:int(uint32, row, 12);
1143 1171 a.ptr.knownsince = r:int(int64,row, 10);
1144 1172 a.ptr.avatarid = r:int(uint64,row, 13);
1145 - if r:null(row,8) then
1146 - a.ptr.key.ct = 0 a.ptr.key.ptr = nil
1147 - else
1148 - a.ptr.key = r:bin(row,8)
1149 - end
1150 1173 a.ptr.origin = origin
1151 1174 if avia.buf ~= nil then avia:free() end
1152 1175 return a
1153 1176 end
1154 1177
1155 1178 local privmap = lib.store.powmap
1156 1179
................................................................................
1464 1487 blacklist = res:bool(i, 3);
1465 1488 pubkey = res:bin(i, 4);
1466 1489 }
1467 1490 end]
1468 1491 if rsakeys.sz > 0 then defer rsakeys:free()
1469 1492 for i=0, rsakeys.sz do var props = toprops(&rsakeys, i)
1470 1493 lib.dbg('loading next RSA pubkey')
1471 - var pub = lib.crypt.loadpub(props.pubkey.ptr, props.pubkey.ct)
1494 + var pub = lib.crypt.loadpub(props.pubkey)
1472 1495 if pub.ok then defer pub.val:free()
1473 1496 lib.dbg('checking pubkey against response')
1474 1497 var vfy, secl = lib.crypt.verify(&pub.val, token.ptr, token.ct, sig.ptr, sig.ct)
1475 1498 if vfy then
1476 1499 lib.dbg('signature verified')
1477 1500 if props.blacklist then lib.dbg('key blacklisted!') goto fail end
1478 1501 var dupname = lib.str.dup(props.name.ptr)
................................................................................
1539 1562
1540 1563 post_create = [terra(
1541 1564 src: &lib.store.source,
1542 1565 post: &lib.store.post
1543 1566 ): uint64
1544 1567 var r = queries.post_create.exec(src,
1545 1568 post.author,post.subject,post.acl,post.body,
1546 - post.parent,post.posted,post.convoheaduri
1569 + post.parent,post.posted,post.convoheaduri,post.uri
1547 1570 )
1548 1571 if r.sz == 0 then return 0 end
1549 1572 defer r:free()
1550 1573 var id = r:int(uint64,0,0)
1551 1574 post.source = src
1552 1575 return id
1553 1576 end];
................................................................................
2091 2114 if n.kind == lib.store.noticetype.react then
2092 2115 var react = r:_string(0,5)
2093 2116 lib.str.ncpy(n.reaction, react.ptr, lib.math.smallest(react.ct,[(`n.reaction).tree.type.N]))
2094 2117 end
2095 2118
2096 2119 return n
2097 2120 end];
2121 +
2122 + thread_top_find = [terra(
2123 + src: &lib.store.source,
2124 + post: uint64
2125 + ): uint64
2126 + var r = queries.thread_top_find.exec(src,post)
2127 + if r.sz == 0 then return 0 end
2128 + defer r:free()
2129 + return r:int(uint64,0,0)
2130 + end];
2098 2131
2099 2132 thread_latest_arrival_calc = [terra(
2100 2133 src: &lib.store.source,
2101 2134 post: uint64
2102 2135 ): lib.store.timepoint
2103 2136 var r = queries.thread_latest_arrival_calc.exec(src,post)
2104 2137 if r.sz == 0 or r:null(0,0) then return 0 end