parsav  Diff

Differences From Artifact [0ea1a47601]:

To Artifact [1740166796]:


1


2
3
4
5
6
7
8
..
20
21
22
23
24
25
26
27
28
29
30


31
32


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
..
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
...
156
157
158
159
160
161
162
163



































164
165
166
167
168
169
170
...
278
279
280
281
282
283
284




285
286
287
288
289
290
291
292
293
294
295
296
297
...
314
315
316
317
318
319
320
321
322
323

324




325
326

327
328
329
330

331
332













333




334



335



336






337

338
339
340
341
342
343
344
345
346
347
...
550
551
552
553
554
555
556
557










558



















559
-- vim: ft=terra


local queries = {
	conf_get = {
		params = {rawstring}, sql = [[
			select value from parsav_config
				where key = $1::text limit 1
		]];
	};
................................................................................
			delete from parsav_config where
				key = $1::text 
		]];
	};

	actor_fetch_uid = {
		params = {uint64}, sql = [[
			select
				id, nym, handle, origin, bio,
				avataruri, rank, quota, key,
				extract(epoch from knownsince)::bigint



			from parsav_actors


				where id = $1::bigint
		]];
	};

	actor_fetch_xid = {
		params = {lib.mem.ptr(int8)}, sql = [[
			select a.id, a.nym, a.handle, a.origin, a.bio,
			       a.avataruri, a.rank, a.quota, a.key, 
			       extract(epoch from knownsince)::bigint,
				   coalesce(a.handle || '@' || s.domain,
				            '@' || a.handle) as xid,

				coalesce(s.domain,
				        (select value from parsav_config
							where key='domain' limit 1)) as domain

................................................................................
				  (a.origin is null and
					  $1::text = a.handle or
					  $1::text = ('@' || a.handle))
		]];
	};

	actor_auth_pw = {
		params = {lib.mem.ptr(int8),rawstring,lib.mem.ptr(int8),lib.store.inet}, sql = [[
			select a.aid from parsav_auth as a
				left join parsav_actors as u on u.id = a.uid
			where (a.uid is null or u.handle = $1::text or (
					a.uid = 0 and a.name = $1::text
				)) and
				(a.kind = 'trust' or (a.kind = $2::text and a.cred = $3::bytea)) and
				(a.netmask is null or a.netmask >> $4::inet)
................................................................................
		]];
	};

	actor_enum = {
		params = {}, sql = [[
			select a.id, a.nym, a.handle, a.origin, a.bio,
			       a.avataruri, a.rank, a.quota, a.key,
			       extract(epoch from knownsince)::bigint,
				   coalesce(a.handle || '@' || s.domain,
				            '@' || a.handle) as xid
			from parsav_actors a
			left join parsav_servers s on s.id = a.origin
		]];
	};

................................................................................
		]]; -- cheat
	};

	actor_session_fetch = {
		params = {uint64, lib.store.inet}, sql = [[
			select a.id, a.nym, a.handle, a.origin, a.bio,
			       a.avataruri, a.rank, a.quota, a.key,
			       extract(epoch from knownsince)::bigint,
				   coalesce(a.handle || '@' || s.domain,
				            '@' || a.handle) as xid,

			       au.restrict,
						array['post'  ] <@ au.restrict as can_post,
						array['edit'  ] <@ au.restrict as can_edit,
						array['acct'  ] <@ au.restrict as can_acct,
................................................................................
			left join parsav_actors a     on au.uid = a.id
			left join parsav_servers s    on a.origin = s.id

			where au.aid = $1::bigint and au.blacklist = false and
				(au.netmask is null or au.netmask >> $2::inet)
		]];
	};
}




































local struct pqr {
	sz: intptr
	res: &lib.pq.PGresult
}
terra pqr:free() if self.sz > 0 then lib.pq.PQclear(self.res) end end
terra pqr:null(row: intptr, col: intptr)
................................................................................
				;[pqt[lib.store.inet](false)]([args[i]], [&uint8](&ipbuf))
			in &ipbuf[0] end
			dumpers[#dumpers+1] = `lib.io.fmt([tostring(i)..'. got inet\n'])
		elseif ty.ptr_basetype == int8 or ty.ptr_basetype == uint8 then
			counters[i] = `[args[i]].ct
			casts[i] = `[&int8]([args[i]].ptr)
			dumpers[#dumpers+1] = `lib.io.fmt([tostring(i)..'. got ptr %llu %.*s\n'], [args[i]].ct, [args[i]].ct, [args[i]].ptr)




		elseif ty:isintegral() then
			counters[i] = ty.bytes
			casts[i] = `[&int8](&[args[i]])
			dumpers[#dumpers+1] = `lib.io.fmt([tostring(i)..'. got int %llu\n'], [args[i]])
			fixers[#fixers + 1] = quote
				--lib.io.fmt('uid=%llu(%llx)\n',[args[i]],[args[i]])
				[args[i]] = lib.math.netswap(ty, [args[i]])
			end
		end
	end

	terra q.exec(src: &lib.store.source, [args])
		var params = arrayof([&int8], [casts])
................................................................................
			return pqr {0, nil}
		else
			return pqr {ct, res}
		end
	end
end

local terra row_to_actor(r: &pqr, row: intptr): lib.mem.ptr(lib.store.actor)
	var a: lib.mem.ptr(lib.store.actor)


	if r:cols() >= 9 then 




		a = [ lib.str.encapsulate(lib.store.actor, {
			nym = {`r:string(row,1), `r:len(row,1)+1};

			bio = {`r:string(row,4), `r:len(row,4)+1};
			avatar = {`r:string(row,5), `r:len(row,5)+1};
			handle = {`r:string(row, 2); `r:len(row,2) + 1};
			xid = {`r:string(row, 10); `r:len(row,10) + 1};

		}) ]
	else













		a = [ lib.str.encapsulate(lib.store.actor, {




			nym = {`r:string(row,1), `r:len(row,1)+1};



			bio = {`r:string(row,4), `r:len(row,4)+1};



			avatar = {`r:string(row,5), `r:len(row,5)+1};






			handle = {`r:string(row, 2); `r:len(row,2) + 1};

		}) ]
		a.ptr.xid = nil
	end
	a.ptr.id = r:int(uint64, row, 0);
	a.ptr.rights = lib.store.rights_default();
	a.ptr.rights.rank = r:int(uint16, row, 6);
	a.ptr.rights.quota = r:int(uint32, row, 7);
	a.ptr.knownsince = r:int(int64,row, 9);
	if r:null(row,8) then
		a.ptr.key.ct = 0 a.ptr.key.ptr = nil
................................................................................

			return au, a
		end

		::fail:: return [lib.stat   (lib.store.auth) ] { ok = false        },
			            [lib.mem.ptr(lib.store.actor)] { ptr = nil, ct = 0 }
	end];
}






























return b

>
>







 







|
|
<
|
>
>

|
>
>
|




|


|







 







|







 







|







 







|







 







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>





<







 







|
|
<
>
|
>
>
>
>
|
<
>
|
|
<
<
>
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
|
>
>
>
|
>
>
>
>
>
>
|
>
|
<
<







 







|
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

1
2
3
4
5
6
7
8
9
10
..
22
23
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
..
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
..
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
...
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
...
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333

334
335
336
337
338
339
340
...
357
358
359
360
361
362
363
364
365

366
367
368
369
370
371
372

373
374
375


376
377

378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413


414
415
416
417
418
419
420
...
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
-- vim: ft=terra
local pstring = lib.mem.ptr(int8)
local binblob = lib.mem.ptr(uint8)
local queries = {
	conf_get = {
		params = {rawstring}, sql = [[
			select value from parsav_config
				where key = $1::text limit 1
		]];
	};
................................................................................
			delete from parsav_config where
				key = $1::text 
		]];
	};

	actor_fetch_uid = {
		params = {uint64}, sql = [[
			select a.id, a.nym, a.handle, a.origin, a.bio,
			       a.avataruri, a.rank, a.quota, a.key, 

			       extract(epoch from a.knownsince)::bigint,
				   coalesce(a.handle || '@' || s.domain,
				            '@' || a.handle) as xid

			from      parsav_actors  as a
			left join parsav_servers as s
				on a.origin = s.id
			where a.id = $1::bigint
		]];
	};

	actor_fetch_xid = {
		params = {pstring}, sql = [[
			select a.id, a.nym, a.handle, a.origin, a.bio,
			       a.avataruri, a.rank, a.quota, a.key, 
			       extract(epoch from a.knownsince)::bigint,
				   coalesce(a.handle || '@' || s.domain,
				            '@' || a.handle) as xid,

				coalesce(s.domain,
				        (select value from parsav_config
							where key='domain' limit 1)) as domain

................................................................................
				  (a.origin is null and
					  $1::text = a.handle or
					  $1::text = ('@' || a.handle))
		]];
	};

	actor_auth_pw = {
		params = {pstring,rawstring,pstring,lib.store.inet}, sql = [[
			select a.aid from parsav_auth as a
				left join parsav_actors as u on u.id = a.uid
			where (a.uid is null or u.handle = $1::text or (
					a.uid = 0 and a.name = $1::text
				)) and
				(a.kind = 'trust' or (a.kind = $2::text and a.cred = $3::bytea)) and
				(a.netmask is null or a.netmask >> $4::inet)
................................................................................
		]];
	};

	actor_enum = {
		params = {}, sql = [[
			select a.id, a.nym, a.handle, a.origin, a.bio,
			       a.avataruri, a.rank, a.quota, a.key,
			       extract(epoch from a.knownsince)::bigint,
				   coalesce(a.handle || '@' || s.domain,
				            '@' || a.handle) as xid
			from parsav_actors a
			left join parsav_servers s on s.id = a.origin
		]];
	};

................................................................................
		]]; -- cheat
	};

	actor_session_fetch = {
		params = {uint64, lib.store.inet}, sql = [[
			select a.id, a.nym, a.handle, a.origin, a.bio,
			       a.avataruri, a.rank, a.quota, a.key,
			       extract(epoch from a.knownsince)::bigint,
				   coalesce(a.handle || '@' || s.domain,
				            '@' || a.handle) as xid,

			       au.restrict,
						array['post'  ] <@ au.restrict as can_post,
						array['edit'  ] <@ au.restrict as can_edit,
						array['acct'  ] <@ au.restrict as can_acct,
................................................................................
			left join parsav_actors a     on au.uid = a.id
			left join parsav_servers s    on a.origin = s.id

			where au.aid = $1::bigint and au.blacklist = false and
				(au.netmask is null or au.netmask >> $2::inet)
		]];
	};

	post_create = {
		params = {uint64, rawstring, rawstring, rawstring}, sql = [[
			insert into parsav_posts (
				author, subject, acl, body,
				posted, discovered,
				circles, mentions
			) values (
				$1::bigint, case when $2::text = '' then null else $2::text end,
				$3::text, $4::text, 
				now(), now(), array[]::bigint[], array[]::bigint[]
			) returning id
		]]; -- TODO array handling
	};

	instance_timeline_fetch = {
		params = {uint64, uint64, uint64, uint64}, sql = [[
			select true,
				p.id, p.author, p.subject, p.acl, p.body,
				extract(epoch from p.posted    )::bigint,
				extract(epoch from p.discovered)::bigint,
				p.parent, null::text
			from parsav_posts as p
				inner join parsav_actors as a on p.author = a.id
			where
				($1::bigint = 0 or p.posted <= to_timestamp($1::bigint)) and
				($2::bigint = 0 or to_timestamp($2::bigint) < p.posted) and
				(a.origin is null)
			order by (p.posted, p.discovered) desc
			limit case when $3::bigint = 0 then null
			           else $3::bigint end
			offset $4::bigint
		]]
	};
}
				--($5::bool = false or p.parent is null) and

local struct pqr {
	sz: intptr
	res: &lib.pq.PGresult
}
terra pqr:free() if self.sz > 0 then lib.pq.PQclear(self.res) end end
terra pqr:null(row: intptr, col: intptr)
................................................................................
				;[pqt[lib.store.inet](false)]([args[i]], [&uint8](&ipbuf))
			in &ipbuf[0] end
			dumpers[#dumpers+1] = `lib.io.fmt([tostring(i)..'. got inet\n'])
		elseif ty.ptr_basetype == int8 or ty.ptr_basetype == uint8 then
			counters[i] = `[args[i]].ct
			casts[i] = `[&int8]([args[i]].ptr)
			dumpers[#dumpers+1] = `lib.io.fmt([tostring(i)..'. got ptr %llu %.*s\n'], [args[i]].ct, [args[i]].ct, [args[i]].ptr)
		elseif ty.ptr_basetype == bool then
			counters[i] = `1
			casts[i] = `[&int8]([args[i]].ptr)
			-- dumpers[#dumpers+1] = `lib.io.fmt([tostring(i)..'. got bool = %hhu\n'], @[args[i]].ptr)
		elseif ty:isintegral() then
			counters[i] = ty.bytes
			casts[i] = `[&int8](&[args[i]])
			dumpers[#dumpers+1] = `lib.io.fmt([tostring(i)..'. got int %llu\n'], [args[i]])
			fixers[#fixers + 1] = quote

				[args[i]] = lib.math.netswap(ty, [args[i]])
			end
		end
	end

	terra q.exec(src: &lib.store.source, [args])
		var params = arrayof([&int8], [casts])
................................................................................
			return pqr {0, nil}
		else
			return pqr {ct, res}
		end
	end
end

local terra row_to_post(r: &pqr, row: intptr): lib.mem.ptr(lib.store.post)
	--lib.io.fmt("body ptr %p  len %llu\n", r:string(row,5), r:len(row,5))

	--lib.io.fmt("acl ptr %p  len %llu\n", r:string(row,4), r:len(row,4))
	var subj: rawstring, sblen: intptr
	if r:null(row,3)
		then subj = nil sblen = 0
		else subj = r:string(row,3) sblen = r:len(row,3)+1
	end
	var p = [ lib.str.encapsulate(lib.store.post, {

		subject = { `subj, `sblen };
		acl = {`r:string(row,4), `r:len(row,4)+1};
		body = {`r:string(row,5), `r:len(row,5)+1};


		--convoheaduri = { `nil, `0 }; --FIXME
	}) ]

	p.ptr.id = r:int(uint64,row,1)
	p.ptr.author = r:int(uint64,row,2)
	p.ptr.posted = r:int(uint64,row,6)
	p.ptr.discovered = r:int(uint64,row,7)
	if r:null(row,8)
		then p.ptr.parent = 0
		else p.ptr.parent = r:int(uint64,row,8)
	end 
	p.ptr.localpost = r:bool(row,0)

	return p
end
local terra row_to_actor(r: &pqr, row: intptr): lib.mem.ptr(lib.store.actor)
	var a: lib.mem.ptr(lib.store.actor)
	var av: rawstring, avlen: intptr
	var nym: rawstring, nymlen: intptr
	var bio: rawstring, biolen: intptr
	if r:null(row,5) then avlen = 0 av = nil else
		av = r:string(row,5)
		avlen = r:len(row,5)+1
	end
	if r:null(row,1) then nymlen = 0 nym = nil else
		nym = r:string(row,1)
		nymlen = r:len(row,1)+1
	end
	if r:null(row,4) then biolen = 0 bio = nil else
		bio = r:string(row,4)
		biolen = r:len(row,4)+1
	end
	a = [ lib.str.encapsulate(lib.store.actor, {
		nym = {`nym, `nymlen};
		bio = {`bio, `biolen};
		avatar = {`av,`avlen};
		handle = {`r:string(row, 2); `r:len(row,2) + 1};
		xid = {`r:string(row, 10); `r:len(row,10) + 1};
	}) ]


	a.ptr.id = r:int(uint64, row, 0);
	a.ptr.rights = lib.store.rights_default();
	a.ptr.rights.rank = r:int(uint16, row, 6);
	a.ptr.rights.quota = r:int(uint32, row, 7);
	a.ptr.knownsince = r:int(int64,row, 9);
	if r:null(row,8) then
		a.ptr.key.ct = 0 a.ptr.key.ptr = nil
................................................................................

			return au, a
		end

		::fail:: return [lib.stat   (lib.store.auth) ] { ok = false        },
			            [lib.mem.ptr(lib.store.actor)] { ptr = nil, ct = 0 }
	end];

	post_create = [terra(
		src: &lib.store.source,
		post: &lib.store.post
	): uint64
		var r = queries.post_create.exec(src,post.author,post.subject,post.acl,post.body) 
		if r.sz == 0 then return 0 end
		defer r:free()
		var id = r:int(uint64,0,0)
		return id
	end];

	instance_timeline_fetch = [terra(src: &lib.store.source, rg: lib.store.range)
		var r = pqr { sz = 0 }
		if rg.mode == 0 then
			r = queries.instance_timeline_fetch.exec(src,rg.from_time,rg.to_time,0,0)
		elseif rg.mode == 1 then
			r = queries.instance_timeline_fetch.exec(src,rg.from_time,0,rg.to_idx,0)
		elseif rg.mode == 2 then
			r = queries.instance_timeline_fetch.exec(src,0,rg.to_time,0,rg.from_idx)
		elseif rg.mode == 3 then
			r = queries.instance_timeline_fetch.exec(src,0,0,rg.to_idx,rg.from_idx)
		end
		
		var ret: lib.mem.ptr(lib.mem.ptr(lib.store.post)) ret:init(r.sz)
		for i=0,r.sz do ret.ptr[i] = row_to_post(&r, i) end -- MUST FREE ALL

		return ret
	end];
}

return b