-
Notifications
You must be signed in to change notification settings - Fork 25
Extract platform-neutral SQL backend initialization #324
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
48 commits
Select commit
Hold shift + click to select a range
640b301
Add shared SQL backend logger
BenCodez 0840e97
Add shared SQL user schema
BenCodez af8c3bc
Add shared SQL backend lifecycle
BenCodez 1e18b18
Implement shared JDBC user storage
BenCodez 6de1900
Add headless SQLite user backend
BenCodez 52917ab
Add headless MySQL user backend
BenCodez afdaba6
Test headless SQLite persistence lifecycle
BenCodez fe71042
Add explicit SQL backend construction factory
BenCodez 01ecf07
Add SQLite JDBC for headless persistence tests
BenCodez 7267c96
Fix SQL dialect, boolean encoding, and quoted user column access
BenCodez ff16ad3
Derive user SQL dialect from the provider and retain PostgreSQL UUID …
BenCodez 71d6880
Escape SQLite identifiers consistently during schema setup and enumer…
BenCodez 4fccbe0
Test real SQLite boolean compatibility and quoted schema CRUD across …
BenCodez 3de7926
Cover PostgreSQL CRUD and provider dialect selection without a live d…
BenCodez 4d619a7
Fix SQL backend UUID migration and SQLite shutdown lifecycle
BenCodez cc6e47c
Preserve bulk-copy identity and committed SQL write outcomes
BenCodez ef89541
Fix checked-exception rethrow in SQL write cleanup
BenCodez 801fb0a
Preserve declared column definitions during SQL schema expansion
BenCodez 158c8a1
Fix required-column user creation and concurrent SQL schema expansion
BenCodez 7e57c11
Account for existing SimpleAPI CREATE cleanup in schema race tests
BenCodez 79d689f
Fix remaining SQL schema and PostgreSQL write review findings
BenCodez 1de42f0
Align SQL regression fixtures with locking and SimpleAPI cleanup
BenCodez d308470
Preserve SQL schema identity and bound enumeration
BenCodez 2f9dedd
Update PostgreSQL case-rename regression
BenCodez 05b3d26
Fix native booleans and streamed user enumeration
BenCodez bd8c350
Page SQL user enumeration outside callback resources
BenCodez b9a4c35
Fix SQLite paging compile typo
BenCodez c4a1a1e
Preserve raw MySQL enumeration cursor values
BenCodez 8be88c3
Fix SQL batch and boolean review findings
BenCodez ea68d09
Drain SQLite operations before closing
BenCodez faf4c55
Reject new SQLite work while draining active callbacks
BenCodez 888eb42
Update SQL regressions for review fixes
BenCodez 558d6b6
Fix SQL lifecycle review follow-ups
BenCodez 6a7a8d1
Reject ambiguous SQL batch aliases
BenCodez 0747a5c
Update SQLite alias regression expectations
BenCodez 765d4e1
Close SQLite admission race
BenCodez ccf8064
Fix SQL schema and insert follow-ups
BenCodez 5c0fddb
Fix PostgreSQL bit boolean binding
BenCodez d469090
Migrate narrow MySQL UUID columns
BenCodez 0bbe368
Harden SQL decoding and diagnostics
BenCodez fbcff00
Preserve legacy SQL write compatibility
BenCodez 7bdd690
Preserve canonical SQL user identities
BenCodez f63dbd4
Validate retained SQL identity and boolean schemas
BenCodez 96ef5e0
Harden retained SQL schema compatibility
BenCodez 643d0fe
Harden SQL metadata type handling
BenCodez 8ef1a22
Honor retained MySQL storage types
BenCodez 3bf3305
Harden retained SQL schema migration
BenCodez c91e273
Preserve retained SQL column attributes
BenCodez File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
388 changes: 388 additions & 0 deletions
388
...ore/src/main/java/com/bencodez/advancedcore/core/user/storage/sql/JdbcSqlUserStorage.java
Large diffs are not rendered by default.
Oops, something went wrong.
452 changes: 452 additions & 0 deletions
452
...dCore/src/main/java/com/bencodez/advancedcore/core/user/storage/sql/MysqlUserBackend.java
Large diffs are not rendered by default.
Oops, something went wrong.
12 changes: 12 additions & 0 deletions
12
...dCore/src/main/java/com/bencodez/advancedcore/core/user/storage/sql/SqlBackendLogger.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package com.bencodez.advancedcore.core.user.storage.sql; | ||
|
|
||
| public interface SqlBackendLogger { | ||
| SqlBackendLogger NO_OP = new SqlBackendLogger() { | ||
| @Override public void info(String message) {} | ||
| @Override public void warn(String message, Throwable error) {} | ||
| }; | ||
|
|
||
| void info(String message); | ||
|
|
||
| void warn(String message, Throwable error); | ||
| } |
34 changes: 34 additions & 0 deletions
34
...cedCore/src/main/java/com/bencodez/advancedcore/core/user/storage/sql/SqlUserBackend.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| package com.bencodez.advancedcore.core.user.storage.sql; | ||
|
|
||
| import java.util.List; | ||
| import java.util.Objects; | ||
| import java.util.UUID; | ||
| import java.util.function.Consumer; | ||
|
|
||
| import com.bencodez.advancedcore.api.user.UserStorage; | ||
| import com.bencodez.advancedcore.core.user.storage.SqlUserStorage; | ||
|
|
||
| public interface SqlUserBackend extends AutoCloseable { | ||
| /** Materialized compatibility API is intentionally bounded by concrete SQL backends. */ | ||
| int MAX_MATERIALIZED_USERS = 100_000; | ||
|
|
||
| UserStorage storageType(); | ||
|
|
||
| SqlUserStorage user(UUID uuid); | ||
|
|
||
| List<UUID> enumerateUsers(); | ||
|
|
||
| /** | ||
| * Streaming enumeration for large historical user tables. Concrete SQL backends | ||
| * override this to avoid first materializing every UUID in heap. | ||
| */ | ||
| default void forEachUser(Consumer<UUID> consumer) { | ||
| Objects.requireNonNull(consumer, "consumer"); | ||
| enumerateUsers().forEach(consumer); | ||
| } | ||
|
|
||
| boolean isOpen(); | ||
|
|
||
| @Override | ||
| void close(); | ||
| } |
30 changes: 30 additions & 0 deletions
30
.../src/main/java/com/bencodez/advancedcore/core/user/storage/sql/SqlUserBackendFactory.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package com.bencodez.advancedcore.core.user.storage.sql; | ||
|
|
||
| import java.nio.file.Path; | ||
| import java.util.Collection; | ||
| import java.util.Objects; | ||
|
|
||
| import com.bencodez.advancedcore.api.user.usercache.keys.UserDataKey; | ||
| import com.bencodez.simpleapi.sql.mysql.config.MysqlConfig; | ||
|
|
||
| /** | ||
| * Constructs SQL user backends from explicit platform-neutral inputs. Native | ||
| * platform adapters are responsible for translating their configuration and | ||
| * data-directory concepts before calling this factory. | ||
| */ | ||
| public final class SqlUserBackendFactory { | ||
| private SqlUserBackendFactory() { | ||
| } | ||
|
|
||
| public static SqliteUserBackend sqlite(Path dataDirectory, String databaseName, String tableName, | ||
| Collection<? extends UserDataKey> keys, SqlBackendLogger logger) { | ||
| Objects.requireNonNull(keys, "keys"); | ||
| return new SqliteUserBackend(dataDirectory, databaseName, tableName, SqlUserSchema.fromKeys(keys), logger); | ||
| } | ||
|
|
||
| public static MysqlUserBackend mysql(String baseTableName, MysqlConfig config, | ||
| Collection<? extends UserDataKey> keys, SqlBackendLogger logger) { | ||
| Objects.requireNonNull(keys, "keys"); | ||
| return new MysqlUserBackend(baseTableName, config, SqlUserSchema.fromKeys(keys), logger); | ||
| } | ||
| } |
81 changes: 81 additions & 0 deletions
81
...ncedCore/src/main/java/com/bencodez/advancedcore/core/user/storage/sql/SqlUserSchema.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| package com.bencodez.advancedcore.core.user.storage.sql; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Collection; | ||
| import java.util.Collections; | ||
| import java.util.LinkedHashMap; | ||
| import java.util.List; | ||
| import java.util.Locale; | ||
| import java.util.Map; | ||
| import java.util.Objects; | ||
|
|
||
| import com.bencodez.advancedcore.api.user.usercache.keys.UserDataKey; | ||
| import com.bencodez.advancedcore.api.user.usercache.keys.UserDataKeyBoolean; | ||
| import com.bencodez.advancedcore.api.user.usercache.keys.UserDataKeyInt; | ||
| import com.bencodez.simpleapi.sql.DataType; | ||
|
|
||
| public final class SqlUserSchema { | ||
| public static final String UUID_COLUMN = "uuid"; | ||
|
|
||
| public record ColumnDefinition(String name, String sqlType, DataType dataType) { | ||
| public ColumnDefinition { | ||
| Objects.requireNonNull(name, "name"); | ||
| Objects.requireNonNull(sqlType, "sqlType"); | ||
| Objects.requireNonNull(dataType, "dataType"); | ||
| if (name.isBlank()) throw new IllegalArgumentException("Column name cannot be blank"); | ||
| if (sqlType.isBlank()) throw new IllegalArgumentException("SQL type cannot be blank"); | ||
| } | ||
| } | ||
|
|
||
| private final Map<String, ColumnDefinition> columnsByLowerName; | ||
|
|
||
| private SqlUserSchema(Map<String, ColumnDefinition> columnsByLowerName) { | ||
| this.columnsByLowerName = Collections.unmodifiableMap(new LinkedHashMap<>(columnsByLowerName)); | ||
| } | ||
|
|
||
| public static Builder builder() { return new Builder(); } | ||
|
|
||
| public static SqlUserSchema fromKeys(Collection<? extends UserDataKey> keys) { | ||
| Builder builder = builder(); | ||
| for (UserDataKey key : Objects.requireNonNull(keys, "keys")) { | ||
| DataType type = DataType.STRING; | ||
| if (key instanceof UserDataKeyInt) type = DataType.INTEGER; | ||
| else if (key instanceof UserDataKeyBoolean) type = DataType.BOOLEAN; | ||
| builder.column(key.getKey(), key.getColumnType(), type); | ||
| } | ||
| return builder.build(); | ||
| } | ||
|
|
||
| public List<ColumnDefinition> columns() { return new ArrayList<>(columnsByLowerName.values()); } | ||
|
|
||
| public ColumnDefinition column(String name) { | ||
| if (name == null) return null; | ||
| return columnsByLowerName.get(name.toLowerCase(Locale.ROOT)); | ||
| } | ||
|
|
||
| public boolean contains(String name) { return column(name) != null; } | ||
|
|
||
| public static final class Builder { | ||
| private final Map<String, ColumnDefinition> columns = new LinkedHashMap<>(); | ||
|
|
||
| private Builder() { | ||
| columns.put(UUID_COLUMN, new ColumnDefinition(UUID_COLUMN, "VARCHAR(37)", DataType.STRING)); | ||
| } | ||
|
|
||
| public Builder column(String name, String sqlType, DataType dataType) { | ||
| Objects.requireNonNull(name, "name"); | ||
| if (UUID_COLUMN.equalsIgnoreCase(name)) { | ||
| throw new IllegalArgumentException("Column name 'uuid' is reserved for user identity"); | ||
| } | ||
| String canonical = name.toLowerCase(Locale.ROOT); | ||
| ColumnDefinition existing = columns.get(canonical); | ||
| if (existing != null) { | ||
| throw new IllegalArgumentException("Duplicate SQL column name: " + name + " conflicts with " + existing.name()); | ||
| } | ||
| columns.put(canonical, new ColumnDefinition(name, sqlType, dataType)); | ||
| return this; | ||
| } | ||
|
|
||
| public SqlUserSchema build() { return new SqlUserSchema(columns); } | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.