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_update_trigger instead of
65 update on packages_pkgid
68 set package = NEW.package,
69 version = NEW.version,
70 release = NEW.release,
71 description = NEW.description,
72 architecture = NEW.architecture,
75 licenses = NEW.licenses,
76 packager = NEW.packager,
77 build_time = NEW.build_time,
78 install_time = NEW.install_time,
80 where package = OLD.package
81 and version = OLD.version
82 and release = OLD.release
87 -- handle package status history with a logging trigger.
88 create trigger logpkgstatus after update of status on packages
89 begin insert into zpmlog (action,target,info)
90 values (printf('status change %s %s', OLD.status, NEW.status),
91 printf('%s-%s-%s', NEW.package, NEW.version, NEW.release),
94 create table packagetags (
100 set_time integer default (strftime('%s', 'now')),
101 primary key (package,version,release,tag),
102 foreign key (package,version,release) references packages (package,version,release) on delete cascade on update cascade
105 -- files contained in a package
106 create table packagefiles (
112 path text, -- filesystem path
113 mode text not null, -- perms, use text for octal rep?
114 username text not null, -- name of owner
115 groupname text not null, -- group of owner
116 uid integer, -- numeric uid, generally ignored
117 gid integer, -- numeric gid, generally ignored
118 configuration integer not null default 0, -- boolean if config file
119 filetype varchar not null default 'r',
123 -- h hard link -- not supported
124 -- c character special -- not supported
125 -- b block special -- not supported
126 -- c and b device special files add dev number column
127 -- p fifos (i.e. pipe) -- not supported
128 target text, -- link target for links
129 -- device file dev numbers
132 hash text, -- null if not a regular file
133 mtime integer, -- seconds since epoch, finer resolution not needed
134 primary key (package,version,release,path),
135 foreign key (package,version,release)
136 references packages (package,version,release)
137 on delete cascade on update cascade,
138 check (not (filetype = 'l' and target is null)),
139 check (not (filetype = 'h' and target is null)),
140 check (target is null or length(target) between 1 and 4095),
141 check (hash is null or length(hash) between 1 and 1024),
142 check (not (filetype = 'r' and hash is null)),
143 check (not (filetype = 'c' and (devmajor is null or devminor is null))),
144 check (not (filetype = 'b' and (devmajor is null or devminor is null))),
145 check (filetype in ('r','d','s','h','c','b','p')),
146 check(length(username) between 1 and 256),
147 check(length(groupname) between 1 and 256),
148 check (configuration = 0 or configuration = 1)
153 create index packagefile_package_index on packagefiles (package);
154 create index packagefile_path_index on packagefiles (path);
155 create index packagefile_hash_index on packagefiles (hash);
157 create view packagefiles_pkgid as
158 select printf('%s-%s-%s', package, version, release) as pkgid, *,
159 printf('%s:%o:%s:%s', filetype, mode, username, groupname) as mds
163 create trigger packagefiles_update_trigger instead of
164 update on packagefiles_pkgid
167 set package = NEW.package,
168 version = NEW.version,
169 release = NEW.release,
172 username = NEW.username,
173 groupname = NEW.groupname,
176 configuration = NEW.configuration,
177 filetype = NEW.filetype,
179 devmajor = NEW.devmajor,
180 devminor = NEW.devminor,
183 where package = OLD.package
184 and version = OLD.version
185 and release = OLD.release
191 create view installed_ref_count as
192 select I.path, count(*) as refcount
193 from installedfiles I
197 create view sync_status_ref_count as
198 select path, status, count(*) as refcount
199 from packagefiles_status
200 where status in ('installed', 'installing', 'removing')
201 group by path, status
204 create view packagefiles_status as
205 select P.status, PF.*
206 from packagefiles_pkgid PF
207 left join packages_pkgid P on P.pkgid = PF.pkgid
210 create view installedfiles as
211 select * from packagefiles_status
212 where status = 'installed'
215 create view install_status as
217 select 'new' as op, PN.*
218 from packagefiles_status PN
219 left join installed_ref_count RC on RC.path = PN.path
220 where RC.refcount is null
221 and PN.status = 'installing'
225 select 'update' as op, PN.*
226 from packagefiles_status PN
227 inner join installedfiles PI on PI.path = PN.path and PI.package = PN.package
228 left join installed_ref_count RC on RC.path = PN.path
229 where RC.refcount = 1
230 and PN.status = 'installing'
231 and PI.hash is not PN.hash
235 select 'conflict' as op, PI.*
236 from packagefiles_status PN
237 inner join installedfiles PI on PI.path = PN.path and PI.package != PN.package
238 where PN.status = 'installing'
241 select 'remove' as op, PI.*
242 from installedfiles PI
243 left join packagefiles_status PN
244 on PI.path = PN.path and PI.package = PN.package
245 and PI.pkgid != PN.pkgid
246 where PN.path is null
247 and PI.package in (select package from packages where status = 'installing')
250 -- remove files in removing, but not installing
251 select distinct 'remove' as op, PR.*
252 from packagefiles_status PR
253 left join packagefiles_status PN
255 and PR.pkgid != PN.pkgid and PN.status in ('installing', 'installed')
256 where PN.path is null
257 and PR.status = 'removing'
260 create table pathtags (
266 path text, -- filesystem path
268 primary key (package,version,release,path,tag),
269 foreign key (package,version,release,path)
270 references packagefiles on delete cascade on update cascade
275 create view elfdeps as
276 select PF.pkgid, PF.status, PF.path, N.needed as needs,
277 PL.path as library, PL.pkgid provider, PL.status as library_status
278 from packagefiles_status PF
279 join elfneeded N on N.file = PF.hash
280 left join elflibraries L on N.needed = L.soname
281 left join packagefiles_status PL on PL.hash = L.file
284 -- TODO just elf information?
285 -- and just hash, not package?
286 create table elflibraries (
287 file text primary key,
293 create table elfneeded (
295 needed text, -- soname of dependency
296 primary key (file, needed)
301 -- package scripts: table of package, stage, file
302 create table scripts (
308 primary key (package,version,release,stage),
309 foreign key (package,version,release) references packages (package,version,release) on delete cascade on update cascade
312 create view scripts_pkgid as
313 select printf('%s-%s-%s', package, version, release) as pkgid, *
317 -- package dependencies: table of package, dependency, dep type (package, soname)
318 create table packagedeps (
322 requires text, -- package name (only)
325 primary key (package,version,release,package),
326 foreign key (package,version,release) references packages (package,version,release) on delete cascade on update cascade
330 create table provides (
333 label text -- a capability label
336 create table requires (
339 label text -- a capability label
342 create table packagegroups (
348 -- not sure how machine readable this needs to be,
349 -- do not at all for now, figure it out later
350 -- could be worth logging all commands in a history table,
351 -- the zpm driver could do that and capture the exit status
353 -- might want the history table to note a "group" to tie together
354 -- sub-invocations, probably an environment variable set if not
355 -- already set by zpm, probably a uuid or a timestamp
356 create table zpmlog (
357 ts text default (strftime('%Y-%m-%d %H:%M:%f', 'now')),
358 -- timestamp of action
360 target text, -- packagename, repo name, etc
361 info text -- human readable
364 create table history (
365 ts integer, -- again, probably needs timestamp sub second
371 create table repository (
372 name text primary key, -- our name for a repo
374 priority integer not null default 1,
375 refreshed integer -- last refresh time
378 -- urls for downloading packages. possibly unneeded
379 create table repository_packages (
381 pkg text, -- glob pattern? in which case others not needed
387 -- track which repository a package was cloned from, i.e. where we got it
388 create table packagesource (
392 repository text references repository
395 create view syncconflicts as
398 select BASE.*, 'preserved' as rstatus
399 from packagefiles_status BASE
400 join elflibraries EL on EL.file = BASE.hash
402 BASE.status in ('removed', 'updated')
403 and BASE.hash in (select hash from packagefiles_status where
404 status in ('installed'))
407 select distinct BASE.*,
408 case when P.status = 'installing' and BASE.status = 'installed'
410 when BASE.status in ('removed','updated')
411 and BASE.path in (select path from preserved) then
416 from packagefiles_status BASE
417 left join packages P on P.package = BASE.package
418 and BASE.status in ('installed', 'removing')
419 and P.status = 'installing'
421 -- metadata different
423 select path, count(distinct mds) as mdcount,
424 count(distinct hash) as hashcount
426 where SS.rstatus in ('installing', 'installed')
428 having (count(distinct mds) > 1 or count(distinct hash) > 1)
430 select BASE.*, 'hash' as conflict
432 where path in (select path from md_conflict where hashcount > 1)
434 select BASE.*, 'md' as conflict
436 where path in (select path from md_conflict where mdcount > 1)
439 create view syncinfo as
442 select BASE.*, 'preserved' as rstatus
443 from packagefiles_status BASE
444 join elflibraries EL on EL.file = BASE.hash
446 BASE.status in ('removed', 'updated')
447 and BASE.hash in (select hash from packagefiles_status where
448 status in ('installed'))
451 select distinct BASE.*,
452 case when P.status = 'installing' and BASE.status = 'installed'
454 when BASE.status in ('removed','updated')
455 and BASE.path in (select path from preserved) then
460 from packagefiles_status BASE
461 left join packages P on P.package = BASE.package
462 and BASE.status in ('installed', 'removing')
463 and P.status = 'installing'
465 -- new file: in installing, not in installed or updating or removing
468 path,username,uid,groupname,gid,mode,filetype,mtime,hash,
469 target,devminor,devmajor
471 where path not in (select path from syncstatus where
472 rstatus in ('installed', 'updating', 'removing')
474 and rstatus in ('installing')
476 -- modified: retained, but with different metadata
481 SS.uid, SS.groupname, SS.gid, SS.mode,
482 SS.filetype, SS.mtime, SS.hash, SS.target, SS.devminor, SS.devmajor
485 on SS.path = OS.path and SS.pkgid is not OS.pkgid
487 and OS.rstatus in ('installed','updating','removing')
488 and (SS.mds is not OS.mds or SS.hash is not OS.hash)
490 SS.rstatus in ('installing')
492 -- preserve: libraries needed by something in installed or installing
497 where status in ('installed', 'installing')
498 and library is not null
502 path,username,uid,groupname,gid,mode,filetype,mtime,hash,
503 target,devminor,devmajor
505 where path in (select library from needed)
506 and SS.rstatus in ('removing', 'removed')
508 -- remove: cur, not preserved, not in final set
511 path,username,uid,groupname,gid,mode,filetype,mtime,hash,
512 target,devminor,devmajor
515 select path from syncstatus where
516 rstatus in ('installed', 'installing')
518 and path not in (select path from preserve)
519 and rstatus in ('removing', 'updating')
521 -- expired: libraries that had been preserved, but aren't needed now
524 path,username,uid,groupname,gid,mode,filetype,mtime,hash,
525 target,devminor,devmajor
527 where hash in (select file from elflibraries where file is not null)
528 and path not in (select path from preserve)
529 and rstatus in ('removed','updated')
531 select 'update' as op, * from modified
533 select 'remove' as op, * from remove
535 select 'obsolete' as op, * from expired
537 select 'new' as op, * from newfiles
539 select 'preserve' as op, * from preserve