3 PRAGMA application_id = 0x5a504442;
4 PRAGMA user_version = 1;
6 -- should be faster with rowid due to the blob content
7 -- these are really just blobs of data
8 -- TODO copyright and license information should probably
11 hash text primary key, -- sha256 of content
12 size integer, -- bigint? certainly need > 2GB
13 compression text, -- always xz?
18 -- information about packages
19 -- a package is identified by a package,version,release triple
20 create table packages (
21 -- primary key columns
22 package text not null,
23 version text not null, -- the upstream version string
24 release integer not null, -- the local release number
31 licenses text, -- hash of actual license? need table for more than one?
33 build_time integer default (strftime('%s', 'now')),
35 hash text, -- see integ.c for package hash details
36 primary key (package,version,release),
37 check (typeof(package) = 'text'),
38 check (typeof(version) = 'text'),
39 check (typeof(release) = 'integer'),
41 -- enforce name and version conventions
42 check(instr(package,' ') = 0),
43 check(instr(package,'/') = 0),
44 check(instr(package,':') = 0),
45 check(instr(version,' ') = 0),
46 check(instr(version,'-') = 0),
47 check(instr(version,'/') = 0),
48 check(instr(version,':') = 0),
49 check(length(package) < 64),
50 check(length(package) > 0),
51 check(length(version) < 32),
52 check(length(version) > 0)
57 create index package_status_index on packages (status);
58 create index package_package_index on packages (package);
60 create view packages_pkgid as
61 select printf('%s-%s-%s', package, version, release) as pkgid, *
64 create trigger packages_delete_trigger instead of
65 delete on packages_pkgid
67 delete from packages where package = OLD.package
68 and version = OLD.version and release = OLD.release;
71 create trigger packages_update_trigger instead of
72 update on packages_pkgid
75 set package = NEW.package,
76 version = NEW.version,
77 release = NEW.release,
78 description = NEW.description,
79 architecture = NEW.architecture,
82 licenses = NEW.licenses,
83 packager = NEW.packager,
84 build_time = NEW.build_time,
85 install_time = NEW.install_time,
87 where package = OLD.package
88 and version = OLD.version
89 and release = OLD.release
94 -- handle package status history with a logging trigger.
95 create trigger logpkgstatus after update of status on packages
96 begin insert into zpmlog (action,target,info)
97 values (printf('status change %s %s', OLD.status, NEW.status),
98 printf('%s-%s-%s', NEW.package, NEW.version, NEW.release),
101 create table packagetags (
107 set_time integer default (strftime('%s', 'now')),
108 primary key (package,version,release,tag),
109 foreign key (package,version,release) references packages (package,version,release) on delete cascade on update cascade
112 -- files contained in a package
113 create table packagefiles (
119 path text, -- filesystem path
120 mode text not null, -- perms, use text for octal rep?
121 username text not null, -- name of owner
122 groupname text not null, -- group of owner
123 uid integer, -- numeric uid, generally ignored
124 gid integer, -- numeric gid, generally ignored
125 configuration integer not null default 0, -- boolean if config file
126 filetype varchar not null default 'r',
130 -- h hard link -- not supported
131 -- c character special -- not supported
132 -- b block special -- not supported
133 -- c and b device special files add dev number column
134 -- p fifos (i.e. pipe) -- not supported
135 target text, -- link target for links
136 -- device file dev numbers
139 hash text, -- null if not a regular file
140 mtime integer, -- seconds since epoch, finer resolution not needed
141 primary key (package,version,release,path),
142 foreign key (package,version,release)
143 references packages (package,version,release)
144 on delete cascade on update cascade,
145 check (not (filetype = 'l' and target is null)),
146 check (not (filetype = 'h' and target is null)),
147 check (target is null or length(target) between 1 and 4095),
148 check (hash is null or length(hash) between 1 and 1024),
149 check (not (filetype = 'r' and hash is null)),
150 check (not (filetype = 'c' and (devmajor is null or devminor is null))),
151 check (not (filetype = 'b' and (devmajor is null or devminor is null))),
152 check (filetype in ('r','d','l','h','c','b','p')),
153 check(length(username) between 1 and 256),
154 check(length(groupname) between 1 and 256),
155 check (configuration = 0 or configuration = 1)
160 create index packagefile_package_index on packagefiles (package);
161 create index packagefile_path_index on packagefiles (path);
162 create index packagefile_hash_index on packagefiles (hash);
164 create view packagefiles_pkgid as
165 select printf('%s-%s-%s', package, version, release) as pkgid, *,
166 printf('%s:%o:%s:%s', filetype, mode, username, groupname) as mds
170 create trigger packagefiles_update_trigger instead of
171 update on packagefiles_pkgid
174 set package = NEW.package,
175 version = NEW.version,
176 release = NEW.release,
179 username = NEW.username,
180 groupname = NEW.groupname,
183 configuration = NEW.configuration,
184 filetype = NEW.filetype,
186 devmajor = NEW.devmajor,
187 devminor = NEW.devminor,
190 where package = OLD.package
191 and version = OLD.version
192 and release = OLD.release
198 create view installed_ref_count as
199 select I.path, count(*) as refcount
200 from installedfiles I
204 create view sync_status_ref_count as
205 select path, status, count(*) as refcount
206 from packagefiles_status
207 where status in ('installed', 'installing', 'removing')
208 group by path, status
211 create view packagefiles_status as
212 select P.status, PF.*
213 from packagefiles_pkgid PF
214 left join packages_pkgid P on P.pkgid = PF.pkgid
217 create view installedfiles as
218 select * from packagefiles_status
219 where status = 'installed'
222 create view install_status as
224 select 'new' as op, PN.*
225 from packagefiles_status PN
226 left join installed_ref_count RC on RC.path = PN.path
227 where RC.refcount is null
228 and PN.status = 'installing'
232 select 'update' as op, PN.*
233 from packagefiles_status PN
234 inner join installedfiles PI on PI.path = PN.path and PI.package = PN.package
235 left join installed_ref_count RC on RC.path = PN.path
236 where RC.refcount = 1
237 and PN.status = 'installing'
238 and PI.hash is not PN.hash
242 select 'conflict' as op, PI.*
243 from packagefiles_status PN
244 inner join installedfiles PI on PI.path = PN.path and PI.package != PN.package
245 where PN.status = 'installing'
248 select 'remove' as op, PI.*
249 from installedfiles PI
250 left join packagefiles_status PN
251 on PI.path = PN.path and PI.package = PN.package
252 and PI.pkgid != PN.pkgid
253 where PN.path is null
254 and PI.package in (select package from packages where status = 'installing')
257 -- remove files in removing, but not installing
258 select distinct 'remove' as op, PR.*
259 from packagefiles_status PR
260 left join packagefiles_status PN
262 and PR.pkgid != PN.pkgid and PN.status in ('installing', 'installed')
263 where PN.path is null
264 and PR.status = 'removing'
267 create table pathtags (
273 path text, -- filesystem path
275 primary key (package,version,release,path,tag),
276 foreign key (package,version,release,path)
277 references packagefiles on delete cascade on update cascade
282 create view elfdeps as
283 select PF.pkgid, PF.status, PF.path, N.needed as needs,
284 PL.path as library, PL.pkgid provider, PL.status as library_status
285 from packagefiles_status PF
286 join elfneeded N on N.file = PF.hash
287 left join elflibraries L on N.needed = L.soname
288 left join packagefiles_status PL on PL.hash = L.file
291 -- TODO just elf information?
292 -- and just hash, not package?
293 create table elflibraries (
294 file text primary key,
300 create table elfneeded (
302 needed text, -- soname of dependency
303 primary key (file, needed)
308 -- package scripts: table of package, stage, file
309 create table scripts (
315 primary key (package,version,release,stage),
316 foreign key (package,version,release) references packages (package,version,release) on delete cascade on update cascade
319 create view scripts_pkgid as
320 select printf('%s-%s-%s', package, version, release) as pkgid, *
324 -- package dependencies: table of package, dependency, dep type (package, soname)
325 create table packagedeps (
329 requires text, -- package name (only)
332 primary key (package,version,release,package),
333 foreign key (package,version,release) references packages (package,version,release) on delete cascade on update cascade
337 create table provides (
340 label text -- a capability label
343 create table requires (
346 label text -- a capability label
349 create table packagegroups (
355 -- not sure how machine readable this needs to be,
356 -- do not at all for now, figure it out later
357 -- could be worth logging all commands in a history table,
358 -- the zpm driver could do that and capture the exit status
360 -- might want the history table to note a "group" to tie together
361 -- sub-invocations, probably an environment variable set if not
362 -- already set by zpm, probably a uuid or a timestamp
363 create table zpmlog (
364 ts text default (strftime('%Y-%m-%d %H:%M:%f', 'now')),
365 -- timestamp of action
367 target text, -- packagename, repo name, etc
368 info text -- human readable
371 create table history (
372 ts integer, -- again, probably needs timestamp sub second
378 create table repository (
379 name text primary key, -- our name for a repo
381 priority integer not null default 1,
382 refreshed integer -- last refresh time
385 -- urls for downloading packages. possibly unneeded
386 create table repository_packages (
388 pkg text, -- glob pattern? in which case others not needed
394 -- track which repository a package was cloned from, i.e. where we got it
395 create table packagesource (
399 repository text references repository
402 create view syncconflicts as
405 select BASE.*, 'preserved' as rstatus
406 from packagefiles_status BASE
407 join elflibraries EL on EL.file = BASE.hash
409 BASE.status in ('removed', 'updated')
410 and BASE.hash in (select hash from packagefiles_status where
411 status in ('installed'))
414 select distinct BASE.*,
415 case when P.status = 'installing' and BASE.status = 'installed'
417 when BASE.status in ('removed','updated')
418 and BASE.path in (select path from preserved) then
423 from packagefiles_status BASE
424 left join packages P on P.package = BASE.package
425 and BASE.status in ('installed', 'removing')
426 and P.status = 'installing'
428 -- metadata different
430 select path, count(distinct mds) as mdcount,
431 count(distinct hash) as hashcount
433 where SS.rstatus in ('installing', 'installed')
435 having (count(distinct mds) > 1 or count(distinct hash) > 1)
437 select BASE.*, 'hash' as conflict
439 where path in (select path from md_conflict where hashcount > 1)
441 select BASE.*, 'md' as conflict
443 where path in (select path from md_conflict where mdcount > 1)
446 create view syncinfo as
449 select BASE.*, 'preserved' as rstatus
450 from packagefiles_status BASE
451 join elflibraries EL on EL.file = BASE.hash
453 BASE.status in ('removed', 'updated')
454 and BASE.hash in (select hash from packagefiles_status where
455 status in ('installed'))
458 select distinct BASE.*,
459 case when P.status = 'installing' and BASE.status = 'installed'
461 when BASE.status in ('removed','updated')
462 and BASE.path in (select path from preserved) then
467 from packagefiles_status BASE
468 left join packages P on P.package = BASE.package
469 and BASE.status in ('installed', 'removing')
470 and P.status = 'installing'
472 -- new file: in installing, not in installed or updating or removing
475 path,username,uid,groupname,gid,mode,filetype,mtime,hash,
476 target,devminor,devmajor
478 where path not in (select path from syncstatus where
479 rstatus in ('installed', 'updating', 'removing')
481 and rstatus in ('installing')
483 -- modified: retained, but with different metadata
488 SS.uid, SS.groupname, SS.gid, SS.mode,
489 SS.filetype, SS.mtime, SS.hash, SS.target, SS.devminor, SS.devmajor
492 on SS.path = OS.path and SS.pkgid is not OS.pkgid
494 and OS.rstatus in ('installed','updating','removing')
495 and (SS.mds is not OS.mds or SS.hash is not OS.hash)
497 SS.rstatus in ('installing')
499 -- preserve: libraries needed by something in installed or installing
504 where status in ('installed', 'installing')
505 and library is not null
509 path,username,uid,groupname,gid,mode,filetype,mtime,hash,
510 target,devminor,devmajor
512 where path in (select library from needed)
513 and SS.rstatus in ('removing', 'removed')
515 -- remove: cur, not preserved, not in final set
518 path,username,uid,groupname,gid,mode,filetype,mtime,hash,
519 target,devminor,devmajor
522 select path from syncstatus where
523 rstatus in ('installed', 'installing')
525 and path not in (select path from preserve)
526 and rstatus in ('removing', 'updating')
528 -- expired: libraries that had been preserved, but aren't needed now
531 path,username,uid,groupname,gid,mode,filetype,mtime,hash,
532 target,devminor,devmajor
534 where hash in (select file from elflibraries where file is not null)
535 and path not in (select path from preserve)
536 and rstatus in ('removed','updated')
538 select 'update' as op, * from modified
540 select 'remove' as op, * from remove
542 select 'obsolete' as op, * from expired
544 select 'new' as op, * from newfiles
546 select 'preserve' as op, * from preserve