]> pd.if.org Git - zpackage/blob - schema/main.sql
b0675509e1a6884e8b2ba6560a91350111bed3fd
[zpackage] / schema / main.sql
1 PRAGMA application_id = 0x5a504442;
2 PRAGMA user_version = 1;
3
4 -- should be faster with rowid due to the blob content
5 -- these are really just blobs of data
6 -- TODO copyright and license information should probably
7 -- go here
8 CREATE TABLE files (
9         hash text primary key, -- sha256 of content
10         size integer, -- bigint?  certainly need > 2GB
11         compression text, -- always xz?
12         content blob
13 )
14 ;
15
16 create view filerefs as
17 select F.hash,
18 count(PF.hash) + count(S.hash) + count(EL.file) + count(N.file) as refcount
19 from files F
20 left join packagefiles PF on PF.hash = F.hash
21 left join scripts S on S.hash = F.hash
22 left join elflibraries EL on EL.file = F.hash
23 left join notes N on N.file = F.hash
24 group by F.hash
25 ;
26
27 -- information about packages
28 -- a package is identified by a package,version,release triple
29 create table packages (
30         -- primary key columns
31         package text not null,
32         version text not null, -- the upstream version string
33         release integer not null, -- the local release number
34
35         -- metadata columns
36         description     text,
37         architecture    text,
38         url     text,
39         status  text,
40         licenses        text, -- hash of actual license?  need table for more than one?
41         packager        text,
42         build_time      integer default (strftime('%s', 'now')),
43         install_time    integer,
44         hash    text, -- see integ.c for package hash details
45         primary key (package,version,release),
46         check (typeof(package) = 'text'),
47         check (typeof(version) = 'text'),
48         check (typeof(release) = 'integer'),
49         check (release > 0),
50         -- enforce name and version conventions
51         check(instr(package,' ') = 0),
52         check(instr(package,'/') = 0),
53         check(instr(package,':') = 0),
54         check(instr(version,' ') = 0),
55         check(instr(version,'-') = 0),
56         check(instr(version,'/') = 0),
57         check(instr(version,':') = 0),
58         check(length(package) < 64),
59         check(length(package) > 0),
60         check(length(version) < 32),
61         check(length(version) > 0)
62 )
63 without rowid
64 ;
65
66 create index package_status_index on packages (status);
67 create index package_package_index on packages (package);
68
69 create view packages_pkgid as
70 select printf('%s-%s-%s', package, version, release) as pkgid, *
71 from packages;
72
73 create trigger packages_delete_trigger instead of
74 delete on packages_pkgid
75 begin
76         delete from packages where package = OLD.package
77         and version = OLD.version and release = OLD.release;
78 end;
79
80 create trigger packages_update_trigger instead of
81 update on packages_pkgid
82 begin
83         update packages
84         set package = NEW.package,
85         version = NEW.version,
86         release = NEW.release,
87         description = NEW.description,
88         architecture = NEW.architecture,
89         url = NEW.url,
90         status = NEW.status,
91         licenses = NEW.licenses,
92         packager = NEW.packager,
93         build_time = NEW.build_time,
94         install_time = NEW.install_time,
95         hash = NEW.hash
96         where package = OLD.package
97         and version = OLD.version
98         and release = OLD.release
99         ;
100 end
101 ;
102
103 -- handle package status history with a logging trigger.
104 create trigger logpkgstatus after update of status on packages
105 begin insert into zpmlog (action,target,info)
106         values (printf('status change %s %s', OLD.status, NEW.status),
107                 printf('%s-%s-%s', NEW.package, NEW.version, NEW.release),
108                 NULL); END;
109
110 create table packagetags (
111         -- package id triple
112         package text,
113         version text,
114         release integer,
115         tag     text,
116         set_time integer default (strftime('%s', 'now')),
117         primary key (package,version,release,tag),
118         foreign key (package,version,release) references packages (package,version,release) on delete cascade on update cascade
119 );
120
121 -- files contained in a package
122 create table packagefiles (
123         -- package id triple
124         package text,
125         version text,
126         release integer,
127
128         path    text, -- filesystem path
129         mode    text not null default '0644', -- perms, use text for octal rep?
130         username        text not null default 'root', -- name of owner
131         groupname       text not null default 'root', -- group of owner
132         uid     integer, -- numeric uid, generally ignored
133         gid     integer, -- numeric gid, generally ignored
134         configuration integer not null default 0, -- boolean if config file
135         confhash text, -- last hash on disk
136         filetype varchar not null default 'r',
137         -- r regular file
138         -- d directory
139         -- l symlink
140         -- h hard link -- not supported
141         -- c character special -- not supported
142         -- b block special -- not supported
143         -- c and b device special files add dev number column
144         -- p fifos (i.e. pipe) -- not supported
145         -- s unix domain socket -- not supported
146         target  text, -- link target for links
147         device  integer, -- device file dev_t
148         hash    text, -- null if not a regular file
149         mtime   integer, -- seconds since epoch, finer resolution not needed
150         primary key (package,version,release,path),
151         foreign key (package,version,release)
152                 references packages (package,version,release)
153                 on delete cascade on update cascade,
154         check (not (filetype = 'l' and target is null)),
155         check (not (filetype = 'h' and target is null)),
156         check (target is null or length(target) between 1 and 4095),
157         check (hash is null or length(hash) between 1 and 1024),
158         check (path not in ('.', '..')),
159         check (not (filetype = 'r' and hash is null)),
160         check (not (filetype = 'c' and device is null)),
161         check (not (filetype = 'b' and device is null)),
162         check (filetype in ('r','d','l','h','c','b','p')),
163         check(length(username) between 1 and 256),
164         check(length(groupname) between 1 and 256),
165         check (configuration = 0 or configuration = 1)
166 )
167 without rowid
168 ;
169
170 create index packagefile_package_index on packagefiles (package);
171 create index packagefile_path_index on packagefiles (path);
172 create index packagefile_hash_index on packagefiles (hash);
173 create index pkgfile_configuration on packagefiles (configuration) where configuration = 1;
174
175 create view packagefiles_pkgid as
176 select printf('%s-%s-%s', package, version, release) as pkgid, *,
177 printf('%s:%s:%s:%s', filetype, mode, username, groupname) as mds
178 from packagefiles
179 ;
180
181 create trigger packagefiles_update_trigger instead of
182 update on packagefiles_pkgid
183 begin
184         update packagefiles
185         set package = NEW.package,
186         version = NEW.version,
187         release = NEW.release,
188         path = NEW.path,
189         mode = NEW.mode,
190         username = NEW.username,
191         groupname = NEW.groupname,
192         uid = NEW.uid,
193         gid = NEW.gid,
194         configuration = NEW.configuration,
195         filetype = NEW.filetype,
196         target = NEW.target,
197         device = NEW.device,
198         hash = NEW.hash,
199         mtime = NEW.mtime
200         where package = OLD.package
201         and version = OLD.version
202         and release = OLD.release
203         and path = OLD.path
204         ;
205 end
206 ;
207
208 create trigger packagefiles_delete_trigger instead of
209 delete on packagefiles_pkgid
210 begin
211         delete from packagefiles
212         where package = OLD.package
213         and version = OLD.version
214         and release = OLD.release
215         and path = OLD.path
216         ;
217         update packages set hash = null
218         where package = OLD.package
219         and version = OLD.version
220         and release = OLD.release
221         ;
222 end
223 ;
224
225 create view installed_ref_count as
226 select I.path, count(*) as refcount
227 from installedfiles I
228 group by I.path
229 ;
230
231 create view sync_status_ref_count as
232 select path, status, count(*) as refcount
233 from packagefiles_status
234 where status in ('installed', 'installing', 'removing')
235 group by path, status
236 ;
237
238 create view packagefiles_status as
239 select P.status, PF.*
240 from packagefiles_pkgid PF
241 left join packages_pkgid P on P.pkgid = PF.pkgid
242 ;
243
244 create view installedfiles as
245 select * from packagefiles_status
246 where status = 'installed'
247 ;
248
249 create table pathtags (
250         -- package id triple
251         package text,
252         version text,
253         release integer,
254
255         path    text, -- filesystem path
256         tag     text,
257         primary key (package,version,release,path,tag),
258         foreign key (package,version,release,path)
259         references packagefiles on delete cascade on update cascade
260 )
261 without rowid
262 ;
263
264 create view elfdeps as
265 select PF.pkgid, PF.status, PF.path, N.needed as needs,
266 PL.path as library, PL.pkgid provider, PL.status as library_status
267 from packagefiles_status PF
268 join elfneeded N on N.file = PF.hash
269 left join elflibraries L on N.needed = L.soname
270 left join packagefiles_status PL on PL.hash = L.file
271 ;
272
273 -- TODO just elf information?
274 -- and just hash, not package?
275 create table elflibraries (
276         file    text primary key,
277         soname  text
278 )
279 without rowid
280 ;
281 create index elf_library_name_index on elflibraries(soname);
282
283 create table elfneeded (
284         file    text, -- hash of file
285         needed  text, -- soname of dependency
286         primary key (file, needed)
287 )
288 without rowid
289 ;
290
291 create view package_libraries as
292 select distinct PF.pkgid, EL.soname
293 from packagefiles_pkgid PF join elflibraries EL on PF.hash = EL.file
294 ;
295
296 create view package_libraries_needed as
297 with pkglibs as (
298                 select distinct EN.needed as soname, PF.pkgid
299                 from elfneeded EN
300                 join packagefiles_pkgid PF on PF.hash = EN.file
301                 ),
302      pkgprovides as (
303                      select distinct EL.soname, PF.pkgid
304                      from elflibraries EL
305                      join packagefiles_pkgid PF on PF.hash = EL.file
306                     )
307      select distinct PL.pkgid,PL.soname, PP.soname is not null as selfsatisfied
308      from pkglibs PL
309      left join pkgprovides PP on PL.pkgid = PP.pkgid and PL.soname = PP.soname
310 ;
311
312 -- package scripts: table of package, stage, file
313 create table scripts (
314         package text,
315         version text,
316         release integer,
317         stage   text,
318         hash    text,
319         primary key (package,version,release,stage),
320         foreign key (package,version,release) references packages (package,version,release) on delete cascade on update cascade
321 );
322
323 create view scripts_pkgid as
324 select printf('%s-%s-%s', package, version, release) as pkgid, *
325 from scripts
326 ;
327
328 -- package dependencies: table of package, dependency, dep type (package, soname)
329 create table packagedeps (
330         package text,
331         version text,
332         release integer,
333         requires text, -- package, can be partial
334         primary key (package,version,release,package),
335         foreign key (package,version,release) references packages (package,version,release) on delete cascade on update cascade
336 );
337
338 -- capability labels
339 create table provides (
340         package text,
341         subpackage      text,
342         label   text -- a capability label
343 );
344
345 create table requires (
346         package text,
347         subpackage      text,
348         label   text -- a capability label
349 );
350
351 create table packagegroups (
352         package text,
353         "group" text
354 );
355
356 -- zpm actions
357 -- not sure how machine readable this needs to be,
358 -- do not at all for now, figure it out later
359 -- could be worth logging all commands in a history table,
360 -- the zpm driver could do that and capture the exit status
361 -- as well
362 -- might want the history table to note a "group" to tie together
363 -- sub-invocations, probably an environment variable set if not
364 -- already set by zpm, probably a uuid or a timestamp
365 create table zpmlog (
366         ts      text default (strftime('%Y-%m-%d %H:%M:%f', 'now')),
367         -- timestamp of action
368         action  text,
369         target  text, -- packagename, repo name, etc
370         info    text -- human readable
371 );
372
373 create table notes (
374         id      integer primary key, -- rowid alias
375         ts      text default (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
376         note    text not null,
377         pkgid   text, -- package
378         path    text, -- file path involved
379         file    text, -- hash of file
380         ack     integer default 0
381 );
382
383 create table history (
384         ts      integer, -- again, probably needs timestamp sub second
385         cmd     text,
386         args    text,
387         status  integer
388 );
389
390 create table repository (
391         name    text primary key, -- our name for a repo
392         url     text not null,
393         priority        integer not null default 1,
394         refreshed       integer -- last refresh time
395 );
396 -- force the url to be repourl/info.repo
397 -- package urls repourl/pkgid.zpm
398
399 -- urls for downloading packages.  possibly unneeded
400 create table repository_packages (
401         repo    text,
402         pkg     text, -- glob pattern?  in which case others not needed
403         version text,
404         release text,
405         url     text
406 );
407
408 -- track which repository a package was cloned from, i.e. where we got it
409 create table packagesource (
410         name    text,
411         version text,
412         release integer,
413         repository      text references repository
414 );
415
416
417 create view needed_libraries as
418 with recursive
419 libs(file,needs,provider) as (
420         select N.file, N.needed as needs, L.file as provider
421         from elfneeded N left join elflibraries L on N.needed = L.soname
422         union
423         select L.file, N.needed as needs, EL.file as provider
424         from libs L
425         join elfneeded N on N.file = L.provider
426         left join elflibraries EL on N.needed = EL.soname
427 )
428 select * from libs;
429
430 /*
431  * tables for repository info, essentially materalized views
432  */
433 create table repository_libs (
434         pkgid text,
435         soname text
436 );
437
438 create table repository_libsneeded (
439         pkgid text,
440         soname text,
441         selfsat integer
442 );