Further sproc updates.

This commit is contained in:
Josh Stark 2019-12-10 22:37:49 +00:00
parent a48d47938e
commit 70a91c0d92
5 changed files with 318 additions and 46 deletions

View File

@ -27,7 +27,6 @@ import io.linuxserver.fleet.v2.types.*;
import io.linuxserver.fleet.v2.types.internal.ImageOutlineRequest;
import io.linuxserver.fleet.v2.types.internal.TagBranchOutlineRequest;
import io.linuxserver.fleet.v2.types.meta.ItemSyncSpec;
import sun.util.locale.provider.LocaleServiceProviderPool;
import java.sql.*;
import java.util.ArrayList;
@ -37,17 +36,16 @@ import java.util.Set;
public class DefaultImageDAO extends AbstractDAO implements ImageDAO {
private static final String GetRepository = "{CALL Repository_Get(?)}";
private static final String GetImageKeys = "{CALL Repository_GetImageKeys(?)}";
private static final String GetRepository = "{CALL Repository_Get(?)}";
private static final String GetImageKeys = "{CALL Repository_GetImageKeys(?)}";
private static final String StoreImage = "{CALL Image_Store(?,?,?,?,?,?,?,?,?,?)}";
private static final String StoreTagBranch = "{CALL Image_StoreTagBranch(?,?,?,?)}";
private static final String StoreTagDigest = "{CALL Image_StoreTagDigest(?,?,?,?,?)}";
private static final String CreateImageOutline = "{CALL Image_CreateOutline(?,?,?,?)}";
private static final String GetImage = "{CALL Image_Get(?)}";
private static final String GetTagBranches = "{CALL Image_GetTagBranches(?)}";
private static final String GetTagDigests = "{CALL Image_GetTagDigests(?)}";
private static final String DeleteImage = "{CALL Image_Delete(?)}";
private static final String StoreImage = "{CALL Image_Store(?,?,?,?,?,?,?,?,?,?)}";
private static final String CreateTagBranchOutline = "{CALL Image_CreateTagBranchOutline(?,?)}";
private static final String StoreTagDigest = "{CALL Image_StoreTagDigest(?,?,?,?,?)}";
private static final String CreateImageOutline = "{CALL Image_CreateOutline(?,?,?,?)}";
private static final String GetImage = "{CALL Image_Get(?)}";
private static final String GetTagBranches = "{CALL Image_GetTagBranches(?)}";
private static final String DeleteImage = "{CALL Image_Delete(?)}";
public DefaultImageDAO(final DefaultDatabaseConnection databaseConnection) {
super(databaseConnection);
@ -132,32 +130,28 @@ public class DefaultImageDAO extends AbstractDAO implements ImageDAO {
}
@Override
public InsertUpdateResult<TagBranch> storeTagBranchOutline(final TagBranchOutlineRequest request) {
public InsertUpdateResult<TagBranch> createTagBranchOutline(final TagBranchOutlineRequest request) {
try (final Connection connection = getConnection()) {
try (final CallableStatement call = connection.prepareCall(StoreTagBranch)) {
try (final CallableStatement call = connection.prepareCall(CreateTagBranchOutline)) {
int i = 1;
call.setInt(i++, request.getImageKey().getId());
call.setString(i++, request.getBranchName());
call.setString(i++, request.getLatestTag().getVersion());
Utils.setNullableTimestamp(call, i, request.getLatestTag().getBuildDate());
call.setString(i, request.getBranchName());
final ResultSet results = call.executeQuery();
if (results.next()) {
storeTagDigests(connection, makeTagBranchKey(results, request.getImageKey()), request.getLatestTag().getDigests());
return new InsertUpdateResult<>(makeTagBranch(results, connection, request.getImageKey()));
return new InsertUpdateResult<>(makeTagBranch(results, call, request.getImageKey()));
}
return new InsertUpdateResult<>(InsertUpdateStatus.FAILED, "storeTagBranchOutline did not return anything.");
return new InsertUpdateResult<>(InsertUpdateStatus.FAILED, "createTagBranchOutline did not return anything.");
}
} catch (SQLException e) {
getLogger().error("Error caught when executing SQL: storeTagBranchOutline", e);
getLogger().error("Error caught when executing SQL: createTagBranchOutline", e);
return new InsertUpdateResult<>(InsertUpdateStatus.FAILED, e.getMessage());
}
}
@ -355,40 +349,37 @@ public class DefaultImageDAO extends AbstractDAO implements ImageDAO {
final ResultSet results = call.executeQuery();
while (results.next()) {
image.addTagBranch(makeTagBranch(results, connection, image.getKey()));
image.addTagBranch(makeTagBranch(results, call, image.getKey()));
}
}
}
private TagBranch makeTagBranch(final ResultSet results, final Connection connection, final ImageKey imageKey) throws SQLException {
private TagBranch makeTagBranch(final ResultSet results, final CallableStatement call, final ImageKey imageKey) throws SQLException {
final TagBranchKey branchKey = makeTagBranchKey(results, imageKey);
return new TagBranch(branchKey,
return new TagBranch(makeTagBranchKey(results, imageKey),
results.getString("BranchName"),
makeTag(results, connection, branchKey));
results.getBoolean("BranchProtected"),
makeTag(results, call));
}
private TagBranchKey makeTagBranchKey(ResultSet results, ImageKey imageKey) throws SQLException {
return new TagBranchKey(results.getInt("BranchId"), imageKey);
}
private Tag makeTag(final ResultSet results, final Connection connection, final TagBranchKey tagBranchKey) throws SQLException {
private Tag makeTag(final ResultSet results, final CallableStatement call) throws SQLException {
return new Tag(results.getString("TagVersion"),
results.getTimestamp("TagBuildDate").toLocalDateTime(),
makeTagDigests(tagBranchKey, connection));
makeTagDigests(call));
}
private Set<TagDigest> makeTagDigests(final TagBranchKey tagBranchKey, final Connection connection) throws SQLException {
private Set<TagDigest> makeTagDigests(final CallableStatement call) throws SQLException {
final Set<TagDigest> digests = new HashSet<>();
try (final CallableStatement call = connection.prepareCall(GetTagDigests)) {
while (call.getMoreResults() && call.getUpdateCount() == -1) {
call.setInt(1, tagBranchKey.getId());
final ResultSet results = call.executeQuery();
final ResultSet results = call.getResultSet();
while (results.next()) {
digests.add(makeTagDigest(results));
}

View File

@ -34,7 +34,7 @@ public interface ImageDAO {
InsertUpdateResult<Image> createImageOutline(final ImageOutlineRequest request);
InsertUpdateResult<TagBranch> storeTagBranchOutline(final TagBranchOutlineRequest request);
InsertUpdateResult<TagBranch> createTagBranchOutline(final TagBranchOutlineRequest request);
void removeImage(final Image image);

View File

@ -24,20 +24,26 @@ import java.util.concurrent.atomic.AtomicReference;
public class TagBranch extends AbstractHasKey<TagBranchKey> {
private final String branchName;
private final AtomicReference<Tag> latestTag;
private final String branchName;
private final AtomicReference<Boolean> branchProtected;
private final AtomicReference<Tag> latestTag;
public TagBranch(final TagBranchKey tagBranchKey, final String tagBranchName, final Tag latestTag) {
public TagBranch(final TagBranchKey tagBranchKey, final String tagBranchName, final boolean branchProtected, final Tag latestTag) {
super(tagBranchKey);
this.branchName = tagBranchName;
this.latestTag = new AtomicReference<>(latestTag);
this.branchName = tagBranchName;
this.branchProtected = new AtomicReference<>(branchProtected);
this.latestTag = new AtomicReference<>(latestTag);
}
public final void updateLatestTag(final Tag latestTag) {
this.latestTag.set(latestTag);
}
public final void setBranchProtected(final boolean branchProtected) {
this.branchProtected.set(branchProtected);
}
public final String getBranchName() {
return branchName;
}
@ -49,4 +55,8 @@ public class TagBranch extends AbstractHasKey<TagBranchKey> {
public final boolean isNamedLatest() {
return "latest".equals(getBranchName());
}
public final boolean isBranchProtected() {
return branchProtected.get();
}
}

View File

@ -24,13 +24,11 @@ public class TagBranchOutlineRequest {
private final ImageKey imageKey;
private final String branchName;
private final Tag latestTag;
public TagBranchOutlineRequest(final ImageKey imageKey, final String branchName, final Tag latestTag) {
this.imageKey = imageKey;
this.branchName = branchName;
this.latestTag = latestTag;
}
public final ImageKey getImageKey() {
@ -40,8 +38,4 @@ public class TagBranchOutlineRequest {
public final String getBranchName() {
return branchName;
}
public final Tag getLatestTag() {
return latestTag;
}
}

View File

@ -0,0 +1,277 @@
DELIMITER //
CREATE TABLE Repository (
`id` INT NOT NULL auto_increment PRIMARY KEY,
`name` VARCHAR(255) NOT NULL,
`sync_enabled` TINYINT NOT NULL DEFAULT 1,
`version_mask` VARCHAR(255) DEFAULT NULL,
`hidden` TINYINT NOT NULL DEFAULT 0,
`stable` TINYINT NOT NULL DEFAULT 1,
`deprecated` TINYINT NOT NULL DEFAULT 0,
`modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY (`name`)
) ENGINE=InnoDB;
//
CREATE TABLE Image (
`id` INT NOT NULL auto_increment PRIMARY KEY,
`repository` INT NOT NULL,
`name` VARCHAR(255) NOT NULL,
`description` TEXT DEFAULT NULL,
`pulls` BIGINT DEFAULT 0,
`stars` BIGINT DEFAULT 0,
`latest_version` VARCHAR(255) DEFAULT NULL,
`sync_enabled` TINYINT NOT NULL DEFAULT 1,
`version_mask` VARCHAR(255) DEFAULT NULL,
`hidden` TINYINT NOT NULL DEFAULT 0,
`stable` TINYINT NOT NULL DEFAULT 1,
`deprecated` TINYINT NOT NULL DEFAULT 0,
`modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY (`repository`, `name`),
FOREIGN KEY (`repository`) REFERENCES Repository(`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
//
CREATE TABLE TagBranch (
`id` INT NOT NULL auto_increment PRIMARY KEY,
`image_id` INT NOT NULL,
`name` VARCHAR(255) NOT NULL,
`latest_version` VARCHAR(255) NOT NULL DEFAULT 'Unknown',
`protected` TINYINT NOT NULL DEFAULT 0,
`build_date` TIMESTAMP DEFAULT NULL,
UNIQUE KEY (`image_id`, `name`),
FOREIGN KEY (`image_id`) REFERENCES Image(`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
//
CREATE TABLE TagDigest (
`branch_id` INT NOT NULL,
`size` BIGINT NOT NULL,
`arch` VARCHAR(100) NOT NULL,
`digest` VARCHAR(255) NOT NULL,
`variant` VARCHAR(50) DEFAULT NULL,
UNIQUE KEY (`branch_id`, `digest`),
FOREIGN KEY (`branch_id`) REFERENCES TagBranch(`id`)
) ENGINE=InnoDB;
//
CREATE OR REPLACE VIEW `ImageKey_View` AS (
SELECT
image_view.`ImageId`,
image_view.`ImageName`,
image_view.`RepositoryId`,
image_view.`RepositoryName`
FROM
Image_View image_view
);
//
CREATE OR REPLACE VIEW `Image_View` AS (
SELECT
-- Key
images.`id` AS `ImageId`,
images.`name` AS `ImageName`,
images.`repository` AS `RepositoryId`,
repositories.`name` AS `RepositoryName`,
-- Counts
images.`pulls` AS `LatestPullCount`,
images.`stars` AS `LatestStarCount`,
-- Spec
images.`sync_enabled` AS `SyncEnabled`,
images.`version_mask` AS `VersionMask`,
images.`hidden` AS `Hidden`,
images.`stable` AS `Stable`,
images.`deprecated` AS `Deprecated`,
-- General
images.`description` AS `Description`,
images.`modified` AS `LastUpdated`
FROM
Image images
JOIN
Repository repositories ON repositories.`id` = images.`repository`
);
//
CREATE OR REPLACE VIEW `TagBranch_View` AS (
SELECT
`image_id` AS `ImageId`,
`id` AS `BranchId`,
`name` AS `BranchName`,
`latest_version` AS `TagVersion`,
`protected` AS `BranchProtected`,
`build_date` AS `TagBuildDate`
FROM
TagBranch
);
//
CREATE OR REPLACE VIEW `TagDigest_View` AS (
SELECT
tag_branch.`image_id` AS `ImageId`,
tag_branch.`branch_id AS `BranchId`,
tag_digest.`size` AS `DigestSize`,
tag_digest.`digest` AS `DigestSha`,
tag_digest.`arch` AS `DigestArch`,
tag_digest.`variant` AS `DigestVariant`,
FROM
TagDigest tag_digest
JOIN
TagBranch tag_branch ON tag_branch.`id` = tag_digest.`branch_id`
);
//
CREATE OR REPLACE PROCEDURE `Image_GetTagBranches`
(
in_image_id INT
)
BEGIN
-- Top level branch info
SELECT *
FROM
TagBranch_View
WHERE
`image_id` = in_image_id;
-- All digests for the given tag in the branch.
SELECT *
FROM
TagDigest_View tag_digest
WHERE
tag_digest.`ImageId` = in_image_id;
END;
//
CREATE OR REPLACE PROCEDURE `Image_CreateTagBranchOutline`
(
in_image_id INT,
in_branch_name VARCHAR(255)
)
BEGIN
INSERT INTO TagBranch (`image_id`, `name`)
VALUES
(
in_image_id,
in_branch_name
);
-- Top level branch info
SELECT *
FROM
TagBranch_View
WHERE
`BranchId` = LAST_INSERT_ID();
END;
//
CREATE OR REPLACE PROCEDURE `Image_StoreTagDigest`
(
in_branch_id INT,
in_size BIGINT,
in_digest VARCHAR(255)
in_arch VARCHAR(255),
in_variant VARCHAR(100),
OUT out_status enum('Inserted', 'NoChange')
)
BEGIN
IF EXISTS(SELECT `branch_id` FROM TagDigest WHERE `branch_id` = in_branch_id AND `digest` = in_digest) THEN
-- Digests are immutable and cannot be changed. Only new digest can be added.
SET out_status = 'NoChange';
ELSE
INSERT INTO TagDigest (`branch_id`, `size`, `digest`, `arch`, `variant`)
VALUES
(
in_branch_id,
in_size,
in_digest,
in_arch,
in_variant
);
SET out_status = 'Inserted';
END IF;
END;
//
CREATE OR REPLACE PROCEDURE `Image_Get`
(
in_id INT
)
BEGIN
SELECT * FROM Image_View image_view WHERE image_view.`ImageId` = in_id;
END;
//
CREATE OR REPLACE PROCEDURE `Image_Delete`
(
in_id INT,
OUT out_status enum('Updated', 'NoChange')
)
BEGIN
IF EXISTS(SELECT `id` FROM ImagesV2 WHERE `id` = in_id`) THEN
DELETE FROM ImagesV2 WHERE `id` = in_id;
SET out_status = 'Updated';
ELSE
SET out_status = 'NoChange';
END IF;
END;
//
CREATE OR REPLACE PROCEDURE `Image_CreateOutline`
(
in_repository INT,
in_name VARCHAR(255),
in_description TEXT,
in_modified TIMESTAMP,
OUT out_status enum('Inserted', 'NoChange', 'Exists')
)
BEGIN
IF EXISTS(SELECT `id` FROM ImagesV2 WHERE `id` = in_id`) THEN
SET out_status = 'Exists';
ELSE
INSERT INTO ImagesV2 (`repository`, `name`, `description`, `modified`)
VALUES
(
in_repository,
in_name,
in_description,
in_modified
);
SELECT * FROM ImageKey_View image_key WHERE image_key.`ImageId` = LAST_INSERT_ID();
END IF;
END;
//