Flox Package Database 1
CRUD Operations on Nix Package Metadata
Loading...
Searching...
No Matches
schemas.hh
Go to the documentation of this file.
1/* ========================================================================== *
2 *
3 * @file pkgdb/schemas.hh
4 *
5 * @brief SQL Schemas to initialize a package database.
6 *
7 *
8 * -------------------------------------------------------------------------- */
9
10#pragma once
11
12/* -------------------------------------------------------------------------- */
13
14namespace flox::pkgdb {
15
16/* -------------------------------------------------------------------------- */
17
18/* Holds metadata information about schema versions. */
19static const char * sql_versions = R"SQL(
20CREATE TABLE IF NOT EXISTS DbVersions (
21 name TEXT NOT NULL PRIMARY KEY
22, version TEXT NOT NULL
23)
24)SQL";
25
26
27/* -------------------------------------------------------------------------- */
28
29static const char * sql_input = R"SQL(
30CREATE TABLE IF NOT EXISTS LockedFlake (
31 fingerprint TEXT PRIMARY KEY
32, string TEXT NOT NULL
33, attrs JSON NOT NULL
34);
35
36CREATE TRIGGER IF NOT EXISTS IT_LockedFlake AFTER INSERT ON LockedFlake
37 WHEN ( 1 < ( SELECT COUNT( fingerprint ) FROM LockedFlake ) )
38 BEGIN
39 SELECT RAISE( ABORT, 'Cannot write conflicting LockedFlake info.' );
40 END
41)SQL";
42
43
44/* -------------------------------------------------------------------------- */
45
46static const char * sql_attrSets = R"SQL(
47CREATE TABLE IF NOT EXISTS AttrSets (
48 id INTEGER PRIMARY KEY
49, parent INTEGER
50, attrName VARCHAR( 255) NOT NULL
51, done BOOL NOT NULL DEFAULT FALSE
52, CONSTRAINT UC_AttrSets UNIQUE ( parent, attrName )
53);
54
55CREATE UNIQUE INDEX IF NOT EXISTS idx_AttrSets ON AttrSets ( parent, attrName );
56
57CREATE TRIGGER IF NOT EXISTS IT_AttrSets AFTER INSERT ON AttrSets
58 WHEN
59 ( NEW.id = NEW.parent ) OR
60 ( ( SELECT NEW.parent != 0 ) AND
61 ( ( SELECT COUNT( id ) FROM AttrSets WHERE ( NEW.parent = AttrSets.id ) )
62 < 1
63 )
64 )
65 BEGIN
66 SELECT RAISE( ABORT, 'No such AttrSets.id for parent.' );
67 END
68)SQL";
69
70
71/* -------------------------------------------------------------------------- */
72
73static const char * sql_packages = R"SQL(
74CREATE TABLE IF NOT EXISTS Descriptions (
75 id INTEGER PRIMARY KEY
76, description TEXT NOT NULL UNIQUE
77);
78
79CREATE UNIQUE INDEX IF NOT EXISTS idx_Descriptions
80 ON Descriptions ( description );
81
82CREATE TABLE IF NOT EXISTS Packages (
83 id INTEGER PRIMARY KEY
84, parentId INTEGER NOT NULL
85, attrName VARCHAR( 255 ) NOT NULL
86, name VARCHAR( 255 ) NOT NULL
87, pname VARCHAR( 255 )
88, version VARCHAR( 127 )
89, semver VARCHAR( 127 )
90, license VARCHAR( 255 )
91, outputs JSON NOT NULL
92, outputsToInstall JSON
93, broken BOOL
94, unfree BOOL
95, descriptionId INTEGER
96, FOREIGN KEY ( parentId ) REFERENCES AttrSets ( id )
97, FOREIGN KEY ( descriptionId ) REFERENCES Descriptions ( id )
98, CONSTRAINT UC_Packages UNIQUE ( parentId, attrName )
99);
100
101CREATE UNIQUE INDEX IF NOT EXISTS idx_Packages
102 ON Packages ( parentId, attrName )
103)SQL";
104
105
106/* -------------------------------------------------------------------------- */
107
108static const char * sql_views = R"SQL(
109
110-- A JSON list form of the _attribute path_ to an `AttrSets` row.
111CREATE VIEW IF NOT EXISTS v_AttrPaths AS
112 WITH Tree ( id, parent, attrName, subtree, system, path ) AS
113 (
114 SELECT id, parent, attrName
115 , attrName AS subtree
116 , NULL AS system
117 , ( '["' || attrName || '"]' ) AS path
118 FROM AttrSets WHERE ( parent = 0 )
119 UNION ALL SELECT O.id, O.parent
120 , O.attrName
121 , Parent.subtree
122 , iif( ( Parent.system IS NULL ), O.attrName, Parent.system )
123 AS system
124 , json_insert( Parent.path, '$[#]', O.attrName ) AS path
125 FROM AttrSets O INNER JOIN Tree as Parent ON ( Parent.id = O.parent )
126 ) SELECT * FROM Tree;
127
128
129-- Splits semvers into their major, minor, patch, and pre-release tags.
130CREATE VIEW IF NOT EXISTS v_Semvers AS SELECT
131 semver
132, major
133, minor
134, ( iif( ( length( mPatch ) < 1 ), rest, mPatch ) ) AS patch
135, ( iif( ( length( mPatch ) < 1 ), NULL, rest ) ) AS preTag
136FROM (
137 SELECT semver
138 , major
139 , minor
140 , ( substr( rest, 0, instr( rest, '-' ) ) ) AS mPatch
141 , ( substr( rest, instr( rest, '-' ) + 1 ) ) AS rest
142 FROM (
143 SELECT semver
144 , major
145 , ( substr( rest, 0, instr( rest, '.' ) ) ) AS minor
146 , ( substr( rest, instr( rest, '.' ) + 1 ) ) AS rest
147 FROM (
148 SELECT semver
149 , ( substr( semver, 0, instr( semver, '.' ) ) ) AS major
150 , ( substr( semver, instr( semver, '.' ) + 1 ) ) AS rest
151 FROM ( SELECT DISTINCT semver FROM Packages )
152 )
153 )
154) ORDER BY major, minor, patch, preTag DESC NULLS FIRST;
155
156
157-- Supplies additional version information identifying _date_ versions,
158-- and categorizes versions into _types_.
159CREATE VIEW IF NOT EXISTS v_PackagesVersions AS SELECT
160 Packages.id
161, iif( ( Packages.version IS NULL ), NULL
162 , iif( ( Packages.semver IS NOT NULL ), NULL
163 , iif( ( ( SELECT Packages.version = date( Packages.version ) )
164 IS NOT NULL )
165 , date( Packages.version ), NULL
166 )
167 )
168 ) AS versionDate
169, iif( ( Packages.version IS NULL ), 3
170 , iif( ( Packages.semver IS NOT NULL ), 0
171 , iif( ( ( SELECT Packages.version = date( Packages.version ) )
172 IS NOT NULL )
173 , 1
174 , 3
175 )
176 )
177 )
178 AS versionType
179FROM Packages
180LEFT OUTER JOIN v_Semvers ON ( Packages.semver = v_Semvers.semver );
181
182
183-- Additional information about the _attribute path_ for a `Packages` row.
184CREATE VIEW IF NOT EXISTS v_PackagesPaths AS SELECT
185 Packages.id
186, json_insert( v_AttrPaths.path, '$[#]', Packages.attrName ) AS path
187, json_insert( json_remove( v_AttrPaths.path, '$[1]', '$[0]' )
188 , '$[#]'
189 , Packages.attrName
190 ) AS relPath
191, ( json_array_length( v_AttrPaths.path ) + 1 ) AS depth
192, Packages.attrName AS attrName
193FROM Packages INNER JOIN v_AttrPaths ON ( Packages.parentId = v_AttrPaths.id );
194
195
196-- Aggregates columns used for searching packages.
197CREATE VIEW IF NOT EXISTS v_PackagesSearch AS SELECT
198 Packages.id
199, v_AttrPaths.subtree
200, v_AttrPaths.system
201, v_PackagesPaths.path
202, v_PackagesPaths.relPath
203, v_PackagesPaths.depth
204, Packages.name
205, Packages.attrName
206, Packages.pname
207, v_PackagesPaths.attrName
208, Packages.version
209, v_PackagesVersions.versionDate
210, Packages.semver
211, v_Semvers.major
212, v_Semvers.minor
213, v_Semvers.patch
214, v_Semvers.preTag
215, v_PackagesVersions.versionType
216, Packages.license
217, Packages.broken
218, iif( ( broken IS NULL ), 1, iif( broken, 2, 0 ) ) AS brokenRank
219, Packages.unfree
220, iif( ( unfree IS NULL ), 1, iif( unfree, 2, 0 ) ) AS unfreeRank
221, Descriptions.description
222FROM Packages
223LEFT OUTER JOIN Descriptions ON ( Packages.descriptionId = Descriptions.id )
224LEFT OUTER JOIN v_Semvers ON ( Packages.semver = v_Semvers.semver )
225 INNER JOIN v_AttrPaths ON ( Packages.parentId = v_AttrPaths.id )
226 INNER JOIN v_PackagesPaths ON ( Packages.id = v_PackagesPaths.id )
227 INNER JOIN v_PackagesVersions ON ( Packages.id = v_PackagesVersions.id )
228)SQL";
229
230
231/* -------------------------------------------------------------------------- */
232
233} /* End namespace `flox::pkgdb' */
234
235/* -------------------------------------------------------------------------- *
236 *
237 *
238 *
239 * ========================================================================== */
Interfaces for caching package metadata in SQLite3 databases.
Definition: command.cc:44