diff --git a/plugin/src/main/java/io/lumine/cosmetics/config/Configuration.java b/plugin/src/main/java/io/lumine/cosmetics/config/Configuration.java
index 5e7bf9ee1681faf70ec849dbd34f6a2ddc1c3ead..ccac73d1ad5fd8423094032020333f4bcb6d4a58 100644
--- a/plugin/src/main/java/io/lumine/cosmetics/config/Configuration.java
+++ b/plugin/src/main/java/io/lumine/cosmetics/config/Configuration.java
@@ -1,8 +1,11 @@
 package io.lumine.cosmetics.config;
 
 import com.google.common.collect.Lists;
+
 import io.lumine.cosmetics.MCCosmeticsPlugin;
 import io.lumine.cosmetics.storage.StorageDriver;
+import io.lumine.utils.storage.sql.SqlCredentials;
+import io.lumine.utils.config.properties.types.SqlCredentialsProp;
 import io.lumine.utils.config.properties.Property;
 import io.lumine.utils.config.properties.PropertyHolder;
 import io.lumine.utils.config.properties.types.EnumProp;
@@ -23,8 +26,7 @@ public class Configuration extends ReloadableModule<MCCosmeticsPlugin> implement
     
     private static final IntProp CLOCK_INTERVAL = Property.Int(Scope.CONFIG, "Clock.Interval", 1);
     private static final EnumProp<StorageDriver> STORAGE_DRIVER = Property.Enum(Scope.CONFIG, StorageDriver.class, "Storage.Driver", StorageDriver.JSON); 
-    
-    
+    private static final SqlCredentialsProp SQL_CREDENTIALS = Property.SqlCredentials(Scope.CONFIG, "Storage");
     
     @Getter private boolean allowingMetrics = true;
     
@@ -71,6 +73,10 @@ public class Configuration extends ReloadableModule<MCCosmeticsPlugin> implement
         return STORAGE_DRIVER.get(this);
     }
     
+    public SqlCredentials getSqlCredentials() {
+        return SQL_CREDENTIALS.get(this);
+    }
+    
     private void generateDefaultConfigFiles() {
         final var menuFolder = new File(plugin.getDataFolder(), "menus");
         final var packFolder = new File(plugin.getDataFolder(), "packs");
diff --git a/plugin/src/main/java/io/lumine/cosmetics/players/Profile.java b/plugin/src/main/java/io/lumine/cosmetics/players/Profile.java
index 6b480f666be020da5386e94962e3f93900f9e449..cfc3d01d1152a898da39267c757b37a0737af6c0 100644
--- a/plugin/src/main/java/io/lumine/cosmetics/players/Profile.java
+++ b/plugin/src/main/java/io/lumine/cosmetics/players/Profile.java
@@ -6,6 +6,9 @@ import io.lumine.cosmetics.api.cosmetics.CosmeticVariant;
 import io.lumine.cosmetics.api.cosmetics.EquippedCosmetic;
 import io.lumine.cosmetics.api.players.CosmeticProfile;
 import io.lumine.cosmetics.constants.CosmeticType;
+import io.lumine.cosmetics.storage.sql.SqlStorage;
+import io.lumine.cosmetics.storage.sql.mappings.Keys;
+import io.lumine.cosmetics.storage.sql.mappings.tables.records.ProfileRecord;
 import io.lumine.utils.Schedulers;
 import io.lumine.utils.serialize.Chroma;
 import lombok.Getter;
@@ -30,6 +33,7 @@ public class Profile implements CosmeticProfile,io.lumine.utils.storage.players.
     @Getter private transient final Set<Class<? extends Cosmetic>> hidden = Sets.newConcurrentHashSet();
     @Getter private Map<String,ProfileCosmeticData> equippedCosmetics = Maps.newConcurrentMap();
         
+    @Getter private transient ProfileManager manager;
     @Getter private transient Player player;
     
     public Profile() {}
@@ -39,11 +43,20 @@ public class Profile implements CosmeticProfile,io.lumine.utils.storage.players.
         this.name = name;
     }
     
-    public void initialize(final Player player)  {
+    public void initialize(final ProfileManager manager, final Player player)  {
+        this.manager = manager;
         this.player = player;
         
         reloadCosmetics();
     }
+    
+    public void loadFromSql(ProfileRecord record) {
+        var fetchEquipped = record.fetchChildren(Keys.MCCOSMETICS_PROFILE_EQUIPPED_PROFILE_FK);
+        
+        for(var equipRecord : fetchEquipped) {
+            equippedCosmetics.put(equipRecord.getSlot(), new ProfileCosmeticData(equipRecord));
+        }
+    }
 
     @Override
     public boolean has(Cosmetic cosmetic) {
@@ -55,9 +68,16 @@ public class Profile implements CosmeticProfile,io.lumine.utils.storage.players.
         if(isEquipped(cosmetic)) {
             cosmetic.getManager().unequip(this);
         }
-        equippedCosmetics.put(cosmetic.getType(), new ProfileCosmeticData(cosmetic));
+        
+        final var cosmeticData = new ProfileCosmeticData(cosmetic);
+        
+        equippedCosmetics.put(cosmetic.getType(), cosmeticData);
         equipped.put(cosmetic.getClass(), new EquippedCosmetic(cosmetic));
         cosmetic.getManager().equip(this);
+        
+        if(manager.getAdapter() instanceof SqlStorage sqlStorage) {
+            sqlStorage.saveCosmeticEquipped(this, cosmetic.getType(), cosmeticData);
+        }
     }
 
     @Override
@@ -67,9 +87,15 @@ public class Profile implements CosmeticProfile,io.lumine.utils.storage.players.
             cosmetic.getManager().unequip(this);
         }
 
-        equippedCosmetics.put(cosmetic.getType(), new ProfileCosmeticData(cosmetic));
+        final var cosmeticData = new ProfileCosmeticData(cosmetic);
+        
+        equippedCosmetics.put(cosmetic.getType(), cosmeticData);
         equipped.put(cosmetic.getClass(), new EquippedCosmetic(variant));
         cosmetic.getManager().equip(this);
+        
+        if(manager.getAdapter() instanceof SqlStorage sqlStorage) {
+            sqlStorage.saveCosmeticEquipped(this, cosmetic.getType(), cosmeticData);
+        }
     }
     
     @Override
@@ -77,9 +103,16 @@ public class Profile implements CosmeticProfile,io.lumine.utils.storage.players.
         if(isEquipped(cosmetic)) {
             cosmetic.getManager().unequip(this);
         }
-        equippedCosmetics.put(cosmetic.getType(), new ProfileCosmeticData(cosmetic, color));
+        
+        final var cosmeticData = new ProfileCosmeticData(cosmetic, color);
+        
+        equippedCosmetics.put(cosmetic.getType(), cosmeticData);
         equipped.put(cosmetic.getClass(), new EquippedCosmetic(cosmetic, color));
         cosmetic.getManager().equip(this);
+        
+        if(manager.getAdapter() instanceof SqlStorage sqlStorage) {
+            sqlStorage.saveCosmeticEquipped(this, cosmetic.getType(), cosmeticData);
+        }
     }
 
     @Override
@@ -93,6 +126,10 @@ public class Profile implements CosmeticProfile,io.lumine.utils.storage.players.
         final var pCos = equipped.remove(tClass);
         if(pCos != null) {
             pCos.getCosmetic().getManager().unequip(this);
+            
+            if(manager.getAdapter() instanceof SqlStorage sqlStorage) {
+                sqlStorage.saveCosmeticEquipped(this, pCos.getCosmetic().getId(), null);
+            }
         }
     }
 
diff --git a/plugin/src/main/java/io/lumine/cosmetics/players/ProfileCosmeticData.java b/plugin/src/main/java/io/lumine/cosmetics/players/ProfileCosmeticData.java
index 35450f0cca70c73424f2e738a674e20b76f2e959..036273f64c2230a8af2ffada27949084b72c87f8 100644
--- a/plugin/src/main/java/io/lumine/cosmetics/players/ProfileCosmeticData.java
+++ b/plugin/src/main/java/io/lumine/cosmetics/players/ProfileCosmeticData.java
@@ -6,6 +6,7 @@ import io.lumine.cosmetics.MCCosmeticsPlugin;
 import io.lumine.cosmetics.api.cosmetics.Cosmetic;
 import io.lumine.cosmetics.api.cosmetics.CosmeticVariant;
 import io.lumine.cosmetics.api.cosmetics.EquippedCosmetic;
+import io.lumine.cosmetics.storage.sql.mappings.tables.records.ProfileEquippedRecord;
 import io.lumine.utils.serialize.Chroma;
 import lombok.Data;
 
@@ -34,6 +35,12 @@ public class ProfileCosmeticData {
         this.variant = color.toHexString();
     }
     
+    public ProfileCosmeticData(ProfileEquippedRecord equipRecord) {
+        this.type = equipRecord.getSlot();
+        this.id = equipRecord.getCosmeticId();
+        this.variant = equipRecord.getCosmeticData();
+    }
+
     public Optional<EquippedCosmetic> toEquippedCosmetic() {
         var maybeManager = MCCosmeticsPlugin.inst().getCosmetics().getManager(type);
         if(maybeManager.isEmpty()) {
diff --git a/plugin/src/main/java/io/lumine/cosmetics/players/ProfileManager.java b/plugin/src/main/java/io/lumine/cosmetics/players/ProfileManager.java
index 6f8ee357e78780d906c30292653769fec663b3e8..3315bcdef58634c6b880b28ad2811e2318be71d3 100644
--- a/plugin/src/main/java/io/lumine/cosmetics/players/ProfileManager.java
+++ b/plugin/src/main/java/io/lumine/cosmetics/players/ProfileManager.java
@@ -3,6 +3,8 @@ package io.lumine.cosmetics.players;
 import io.lumine.cosmetics.MCCosmeticsPlugin;
 import io.lumine.cosmetics.api.events.CosmeticPlayerLoadedEvent;
 import io.lumine.cosmetics.api.players.CosmeticProfile;
+import io.lumine.cosmetics.storage.sql.SqlStorage;
+import io.lumine.utils.storage.sql.SqlConnector;
 import io.lumine.utils.Events;
 import io.lumine.utils.logging.Log;
 import io.lumine.utils.storage.players.PlayerRepository;
@@ -19,13 +21,23 @@ public class ProfileManager extends PlayerRepository<MCCosmeticsPlugin,Profile>
     public ProfileManager(MCCosmeticsPlugin plugin) {
         super(plugin, Profile.class);
         
-        switch(plugin.getConfiguration().getStorageType()) {
-            case LUMINE:
-                this.initialize(plugin.getCompatibility().getLumineCore().get().getStorageDriver());
-                break;
-            default:
-                this.initialize(new JsonPlayerStorageAdapter<>(plugin,Profile.class));
-                break;
+        if(plugin.getConfiguration().getStorageType().isSql()) {
+            
+            final var provider = plugin.getConfiguration().getStorageType().getSqlProvider();
+            final var credentials = plugin.getConfiguration().getSqlCredentials();
+            
+            final var connector = new SqlConnector(plugin, provider, credentials);
+            
+            this.initialize(new SqlStorage<>(this,connector));
+        } else {
+            switch(plugin.getConfiguration().getStorageType()) {
+                case LUMINE:
+                    this.initialize(plugin.getCompatibility().getLumineCore().get().getStorageDriver());
+                    break;
+                default:
+                    this.initialize(new JsonPlayerStorageAdapter<>(plugin,Profile.class));
+                    break;
+            }
         }
 
         Events.subscribe(PlayerGameModeChangeEvent.class).handler(event -> {
@@ -51,7 +63,7 @@ public class ProfileManager extends PlayerRepository<MCCosmeticsPlugin,Profile>
 
     @Override
     public void initProfile(Profile profile, Player player) {
-        profile.initialize(player);
+        profile.initialize(this,player);
         Events.call(new CosmeticPlayerLoadedEvent(player,profile));
     }
 
diff --git a/plugin/src/main/java/io/lumine/cosmetics/storage/StorageDriver.java b/plugin/src/main/java/io/lumine/cosmetics/storage/StorageDriver.java
index 22968e3347f3241c607717f4d711c6db3140d1c7..870c3288e23868c4158950ac02ca93b7dd3f7a36 100644
--- a/plugin/src/main/java/io/lumine/cosmetics/storage/StorageDriver.java
+++ b/plugin/src/main/java/io/lumine/cosmetics/storage/StorageDriver.java
@@ -1,8 +1,26 @@
 package io.lumine.cosmetics.storage;
 
+import io.lumine.utils.storage.sql.SqlProvider;
+import lombok.Getter;
+
 public enum StorageDriver {
-    JSON,
-    SQLITE,
-    MYSQL,
-    LUMINE
-}
+    JSON(false),
+    MYSQL(true, SqlProvider.MYSQL),
+    MARIADB(true, SqlProvider.MARIADB),
+    LUMINE(false)
+    
+    ;
+    
+    @Getter private final boolean sql;
+    @Getter private final SqlProvider sqlProvider;
+    
+    private StorageDriver(boolean sql) {
+        this.sql = sql;
+        this.sqlProvider = null;
+    }
+    
+    private StorageDriver(boolean sql, SqlProvider provider) {
+        this.sql = sql;
+        this.sqlProvider = provider;
+    }
+}
\ No newline at end of file
diff --git a/plugin/src/main/java/io/lumine/cosmetics/storage/sql/SqlStorage.java b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/SqlStorage.java
index e706e0e45a4820ac0749c754ebc1ca652657d7d7..9387bc1ccfd79c548562bf980372dbe0a1905402 100644
--- a/plugin/src/main/java/io/lumine/cosmetics/storage/sql/SqlStorage.java
+++ b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/SqlStorage.java
@@ -1,7 +1,14 @@
 package io.lumine.cosmetics.storage.sql;
 
+import java.util.Optional;
 import java.util.UUID;
 
+import io.lumine.cosmetics.players.ProfileCosmeticData;
+import io.lumine.cosmetics.players.ProfileManager;
+import io.lumine.cosmetics.storage.sql.mappings.DefaultSchema;
+import io.lumine.cosmetics.storage.sql.mappings.Tables;
+import io.lumine.utils.lib.jooq.exception.DataAccessException;
+import io.lumine.utils.logging.Log;
 import io.lumine.utils.plugin.LuminePlugin;
 import io.lumine.utils.promise.Promise;
 import io.lumine.utils.storage.players.Profile;
@@ -10,46 +17,121 @@ import io.lumine.utils.storage.sql.SqlConnector;
 
 public class SqlStorage<MCCosmeticsPlugin,CosmeticsProfile> extends SqlPlayerStorageAdapter {
 
-    public SqlStorage(LuminePlugin plugin, SqlConnector connector) {
-        super(plugin, connector);
-        // TODO Auto-generated constructor stub
+    private final ProfileManager manager;
+    
+    public SqlStorage(ProfileManager manager, SqlConnector connector) {
+        super(manager.getPlugin(), connector);
+        this.manager = manager;
+        
+        load(manager.getPlugin());
     }
 
     @Override
-    public void load(LuminePlugin arg0) {
-        // TODO Auto-generated method stub
-        
+    public void load(LuminePlugin plugin) {
+        var connection = getConnector().open();
+
+        try {
+            connection.fetch(Tables.MCCOSMETICS_PROFILE);
+        } catch(DataAccessException ex) {
+            Log.info("Generating database schema...");
+            connection.ddl(DefaultSchema.DEFAULT_SCHEMA).executeBatch();
+        }
     }
 
     @Override
     public void unload() {
-        // TODO Auto-generated method stub
-        
     }
 
     @Override
-    public Promise load(UUID arg0) {
-        // TODO Auto-generated method stub
-        return null;
+    public Promise<Optional<io.lumine.cosmetics.players.Profile>> load(final UUID uuid) {
+        return Promise.supplyingDelayedAsync(() -> {
+            var connection = getConnector().open();
+
+            var fetchProfile = connection.selectFrom(Tables.MCCOSMETICS_PROFILE)
+                .where(Tables.MCCOSMETICS_PROFILE.UUID.eq(uuid.toString()))
+                .fetchAny();
+            
+            if(fetchProfile == null) {
+                return Optional.empty();
+            }
+            
+            var profile = manager.createProfile(UUID.fromString(fetchProfile.getUuid()), fetchProfile.getName());
+
+            profile.loadFromSql(fetchProfile);
+            
+            return Optional.ofNullable(profile);
+        }, 20);
     }
 
     @Override
-    public Promise loadByName(String arg0) {
-        // TODO Auto-generated method stub
-        return null;
+    public Promise<Optional<io.lumine.cosmetics.players.Profile>> loadByName(String name) {
+        return Promise.supplyingAsync(() -> {
+            var connection = getConnector().open();
+
+            var fetchProfile = connection.selectFrom(Tables.MCCOSMETICS_PROFILE)
+                .where(Tables.MCCOSMETICS_PROFILE.NAME.eq(name))
+                .fetchAny();
+            
+            if(fetchProfile == null) {
+                return Optional.empty();
+            }
+            
+            var profile = manager.createProfile(UUID.fromString(fetchProfile.getUuid()), fetchProfile.getName());
+
+            profile.loadFromSql(fetchProfile);
+            
+            return Optional.ofNullable(profile);
+        });
     }
 
     @Override
-    public Promise save(UUID arg0, Profile arg1) {
-        // TODO Auto-generated method stub
-        return null;
+    public Promise<Boolean> save(UUID uuid, Profile profile) {
+        return Promise.supplyingAsync(() -> {
+            return saveSync(uuid,profile);
+        });
     }
 
     @Override
-    public boolean saveSync(UUID arg0, Profile arg1) {
-        // TODO Auto-generated method stub
-        return false;
+    public boolean saveSync(UUID uuid, Profile profile) {
+        var connection = getConnector().open();
+
+        connection.insertInto(Tables.MCCOSMETICS_PROFILE, 
+                                Tables.MCCOSMETICS_PROFILE.UUID, 
+                                Tables.MCCOSMETICS_PROFILE.NAME)
+                .values(uuid.toString(), profile.getName())
+                .onDuplicateKeyUpdate()
+                .set(Tables.MCCOSMETICS_PROFILE.NAME, profile.getName())
+                .returning()
+                .execute();
+
+        return true; 
     }
 
+    public Promise<Boolean> saveCosmeticEquipped(io.lumine.cosmetics.players.Profile profile, String slot, ProfileCosmeticData cosmeticData) {
+        
+        return Promise.supplyingAsync(() -> {
+            var connection = getConnector().open();
+
+            if(cosmeticData != null) {
+                connection.insertInto(Tables.MCCOSMETICS_PROFILE_EQUIPPED, 
+                        Tables.MCCOSMETICS_PROFILE_EQUIPPED.PROFILE_UUID,
+                        Tables.MCCOSMETICS_PROFILE_EQUIPPED.SLOT,
+                        Tables.MCCOSMETICS_PROFILE_EQUIPPED.COSMETIC_ID,
+                        Tables.MCCOSMETICS_PROFILE_EQUIPPED.COSMETIC_DATA)
+                .values(profile.getUniqueId().toString(), slot, cosmeticData.getId(), cosmeticData.getVariant())
+                .onDuplicateKeyUpdate()
+                .set(Tables.MCCOSMETICS_PROFILE_EQUIPPED.COSMETIC_ID, cosmeticData.getId())
+                .set(Tables.MCCOSMETICS_PROFILE_EQUIPPED.COSMETIC_DATA, cosmeticData.getVariant())
+                .execute();
+            } else {
+                connection.deleteFrom(Tables.MCCOSMETICS_PROFILE_EQUIPPED)
+                    .where(Tables.MCCOSMETICS_PROFILE_EQUIPPED.PROFILE_UUID.eq(profile.getUniqueId().toString()),
+                           Tables.MCCOSMETICS_PROFILE_EQUIPPED.SLOT.eq(slot))
+                    .execute();
+            }
 
+            return true;
+        });
+    }
+    
 }
diff --git a/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/DefaultCatalog.java b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/DefaultCatalog.java
new file mode 100644
index 0000000000000000000000000000000000000000..09dd92764dfce0247fd0a91fea812a9f916359cf
--- /dev/null
+++ b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/DefaultCatalog.java
@@ -0,0 +1,54 @@
+/*
+ * This file is generated by jOOQ.
+ */
+package io.lumine.cosmetics.storage.sql.mappings;
+
+
+import java.util.Arrays;
+import java.util.List;
+
+import io.lumine.utils.lib.jooq.Constants;
+import io.lumine.utils.lib.jooq.Schema;
+import io.lumine.utils.lib.jooq.impl.CatalogImpl;
+
+
+/**
+ * This class is generated by jOOQ.
+ */
+@SuppressWarnings({ "all", "unchecked", "rawtypes" })
+public class DefaultCatalog extends CatalogImpl {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * The reference instance of <code>DEFAULT_CATALOG</code>
+     */
+    public static final DefaultCatalog DEFAULT_CATALOG = new DefaultCatalog();
+
+    /**
+     * The schema <code>DEFAULT_SCHEMA</code>.
+     */
+    public final DefaultSchema DEFAULT_SCHEMA = DefaultSchema.DEFAULT_SCHEMA;
+
+    /**
+     * No further instances allowed
+     */
+    private DefaultCatalog() {
+        super("");
+    }
+
+    @Override
+    public final List<Schema> getSchemas() {
+        return Arrays.asList(
+            DefaultSchema.DEFAULT_SCHEMA
+        );
+    }
+
+    /**
+     * A reference to the 3.16 minor release of the code generator. If this
+     * doesn't compile, it's because the runtime library uses an older minor
+     * release, namely: 3.16. You can turn off the generation of this reference
+     * by specifying /configuration/generator/generate/jooqVersionReference
+     */
+    private static final String REQUIRE_RUNTIME_JOOQ_VERSION = Constants.VERSION_3_16;
+}
diff --git a/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/DefaultSchema.java b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/DefaultSchema.java
new file mode 100644
index 0000000000000000000000000000000000000000..d71e3c9c2ec73b79f322f0108ae31300ea44e2ef
--- /dev/null
+++ b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/DefaultSchema.java
@@ -0,0 +1,61 @@
+/*
+ * This file is generated by jOOQ.
+ */
+package io.lumine.cosmetics.storage.sql.mappings;
+
+
+import io.lumine.cosmetics.storage.sql.mappings.tables.MccosmeticsProfile;
+import io.lumine.cosmetics.storage.sql.mappings.tables.MccosmeticsProfileEquipped;
+
+import java.util.Arrays;
+import java.util.List;
+
+import io.lumine.utils.lib.jooq.Catalog;
+import io.lumine.utils.lib.jooq.Table;
+import io.lumine.utils.lib.jooq.impl.SchemaImpl;
+
+
+/**
+ * This class is generated by jOOQ.
+ */
+@SuppressWarnings({ "all", "unchecked", "rawtypes" })
+public class DefaultSchema extends SchemaImpl {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * The reference instance of <code>DEFAULT_SCHEMA</code>
+     */
+    public static final DefaultSchema DEFAULT_SCHEMA = new DefaultSchema();
+
+    /**
+     * The table <code>mccosmetics_profile</code>.
+     */
+    public final MccosmeticsProfile MCCOSMETICS_PROFILE = MccosmeticsProfile.MCCOSMETICS_PROFILE;
+
+    /**
+     * The table <code>mccosmetics_profile_equipped</code>.
+     */
+    public final MccosmeticsProfileEquipped MCCOSMETICS_PROFILE_EQUIPPED = MccosmeticsProfileEquipped.MCCOSMETICS_PROFILE_EQUIPPED;
+
+    /**
+     * No further instances allowed
+     */
+    private DefaultSchema() {
+        super("", null);
+    }
+
+
+    @Override
+    public Catalog getCatalog() {
+        return DefaultCatalog.DEFAULT_CATALOG;
+    }
+
+    @Override
+    public final List<Table<?>> getTables() {
+        return Arrays.asList(
+            MccosmeticsProfile.MCCOSMETICS_PROFILE,
+            MccosmeticsProfileEquipped.MCCOSMETICS_PROFILE_EQUIPPED
+        );
+    }
+}
diff --git a/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/Indexes.java b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/Indexes.java
new file mode 100644
index 0000000000000000000000000000000000000000..2ac4ff42b91241b6ef4ca7b50e5fea764e7c7d9f
--- /dev/null
+++ b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/Indexes.java
@@ -0,0 +1,26 @@
+/*
+ * This file is generated by jOOQ.
+ */
+package io.lumine.cosmetics.storage.sql.mappings;
+
+
+import io.lumine.cosmetics.storage.sql.mappings.tables.MccosmeticsProfileEquipped;
+
+import io.lumine.utils.lib.jooq.Index;
+import io.lumine.utils.lib.jooq.OrderField;
+import io.lumine.utils.lib.jooq.impl.DSL;
+import io.lumine.utils.lib.jooq.impl.Internal;
+
+
+/**
+ * A class modelling indexes of tables in the default schema.
+ */
+@SuppressWarnings({ "all", "unchecked", "rawtypes" })
+public class Indexes {
+
+    // -------------------------------------------------------------------------
+    // INDEX definitions
+    // -------------------------------------------------------------------------
+
+    public static final Index MCCOSMETICS_PROFILE_EQUIPPED_MCCOSMETICS_PROFILE_EQUIPPED_COSMETIC_ID_INDEX = Internal.createIndex(DSL.name("mccosmetics_profile_equipped_cosmetic_id_index"), MccosmeticsProfileEquipped.MCCOSMETICS_PROFILE_EQUIPPED, new OrderField[] { MccosmeticsProfileEquipped.MCCOSMETICS_PROFILE_EQUIPPED.COSMETIC_ID }, false);
+}
diff --git a/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/Keys.java b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/Keys.java
new file mode 100644
index 0000000000000000000000000000000000000000..daa8d6895d805ba1288ef3badbc38902249cc42b
--- /dev/null
+++ b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/Keys.java
@@ -0,0 +1,38 @@
+/*
+ * This file is generated by jOOQ.
+ */
+package io.lumine.cosmetics.storage.sql.mappings;
+
+
+import io.lumine.cosmetics.storage.sql.mappings.tables.MccosmeticsProfile;
+import io.lumine.cosmetics.storage.sql.mappings.tables.MccosmeticsProfileEquipped;
+import io.lumine.cosmetics.storage.sql.mappings.tables.records.ProfileEquippedRecord;
+import io.lumine.cosmetics.storage.sql.mappings.tables.records.ProfileRecord;
+
+import io.lumine.utils.lib.jooq.ForeignKey;
+import io.lumine.utils.lib.jooq.TableField;
+import io.lumine.utils.lib.jooq.UniqueKey;
+import io.lumine.utils.lib.jooq.impl.DSL;
+import io.lumine.utils.lib.jooq.impl.Internal;
+
+
+/**
+ * A class modelling foreign key relationships and constraints of tables in the
+ * default schema.
+ */
+@SuppressWarnings({ "all", "unchecked", "rawtypes" })
+public class Keys {
+
+    // -------------------------------------------------------------------------
+    // UNIQUE and PRIMARY KEY definitions
+    // -------------------------------------------------------------------------
+
+    public static final UniqueKey<ProfileRecord> KEY_MCCOSMETICS_PROFILE_PRIMARY = Internal.createUniqueKey(MccosmeticsProfile.MCCOSMETICS_PROFILE, DSL.name("KEY_mccosmetics_profile_PRIMARY"), new TableField[] { MccosmeticsProfile.MCCOSMETICS_PROFILE.UUID }, true);
+    public static final UniqueKey<ProfileEquippedRecord> KEY_MCCOSMETICS_PROFILE_EQUIPPED_PRIMARY = Internal.createUniqueKey(MccosmeticsProfileEquipped.MCCOSMETICS_PROFILE_EQUIPPED, DSL.name("KEY_mccosmetics_profile_equipped_PRIMARY"), new TableField[] { MccosmeticsProfileEquipped.MCCOSMETICS_PROFILE_EQUIPPED.PROFILE_UUID, MccosmeticsProfileEquipped.MCCOSMETICS_PROFILE_EQUIPPED.SLOT }, true);
+
+    // -------------------------------------------------------------------------
+    // FOREIGN KEY definitions
+    // -------------------------------------------------------------------------
+
+    public static final ForeignKey<ProfileEquippedRecord, ProfileRecord> MCCOSMETICS_PROFILE_EQUIPPED_PROFILE_FK = Internal.createForeignKey(MccosmeticsProfileEquipped.MCCOSMETICS_PROFILE_EQUIPPED, DSL.name("mccosmetics_profile_equipped_profile_fk"), new TableField[] { MccosmeticsProfileEquipped.MCCOSMETICS_PROFILE_EQUIPPED.PROFILE_UUID }, Keys.KEY_MCCOSMETICS_PROFILE_PRIMARY, new TableField[] { MccosmeticsProfile.MCCOSMETICS_PROFILE.UUID }, true);
+}
diff --git a/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/Tables.java b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/Tables.java
new file mode 100644
index 0000000000000000000000000000000000000000..87035e49b1fbdc233404984714e0f0cd41a465d2
--- /dev/null
+++ b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/Tables.java
@@ -0,0 +1,26 @@
+/*
+ * This file is generated by jOOQ.
+ */
+package io.lumine.cosmetics.storage.sql.mappings;
+
+
+import io.lumine.cosmetics.storage.sql.mappings.tables.MccosmeticsProfile;
+import io.lumine.cosmetics.storage.sql.mappings.tables.MccosmeticsProfileEquipped;
+
+
+/**
+ * Convenience access to all tables in the default schema.
+ */
+@SuppressWarnings({ "all", "unchecked", "rawtypes" })
+public class Tables {
+
+    /**
+     * The table <code>mccosmetics_profile</code>.
+     */
+    public static final MccosmeticsProfile MCCOSMETICS_PROFILE = MccosmeticsProfile.MCCOSMETICS_PROFILE;
+
+    /**
+     * The table <code>mccosmetics_profile_equipped</code>.
+     */
+    public static final MccosmeticsProfileEquipped MCCOSMETICS_PROFILE_EQUIPPED = MccosmeticsProfileEquipped.MCCOSMETICS_PROFILE_EQUIPPED;
+}
diff --git a/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/tables/MccosmeticsProfile.java b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/tables/MccosmeticsProfile.java
new file mode 100644
index 0000000000000000000000000000000000000000..cb3711c30710a85aaf70047d8bb939a65b6ae63a
--- /dev/null
+++ b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/tables/MccosmeticsProfile.java
@@ -0,0 +1,134 @@
+/*
+ * This file is generated by jOOQ.
+ */
+package io.lumine.cosmetics.storage.sql.mappings.tables;
+
+
+import io.lumine.cosmetics.storage.sql.mappings.DefaultSchema;
+import io.lumine.cosmetics.storage.sql.mappings.Keys;
+import io.lumine.cosmetics.storage.sql.mappings.tables.records.ProfileRecord;
+
+import io.lumine.utils.lib.jooq.Field;
+import io.lumine.utils.lib.jooq.ForeignKey;
+import io.lumine.utils.lib.jooq.Name;
+import io.lumine.utils.lib.jooq.Record;
+import io.lumine.utils.lib.jooq.Row2;
+import io.lumine.utils.lib.jooq.Schema;
+import io.lumine.utils.lib.jooq.Table;
+import io.lumine.utils.lib.jooq.TableField;
+import io.lumine.utils.lib.jooq.TableOptions;
+import io.lumine.utils.lib.jooq.UniqueKey;
+import io.lumine.utils.lib.jooq.impl.DSL;
+import io.lumine.utils.lib.jooq.impl.SQLDataType;
+import io.lumine.utils.lib.jooq.impl.TableImpl;
+
+
+/**
+ * This class is generated by jOOQ.
+ */
+@SuppressWarnings({ "all", "unchecked", "rawtypes" })
+public class MccosmeticsProfile extends TableImpl<ProfileRecord> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * The reference instance of <code>mccosmetics_profile</code>
+     */
+    public static final MccosmeticsProfile MCCOSMETICS_PROFILE = new MccosmeticsProfile();
+
+    /**
+     * The class holding records for this type
+     */
+    @Override
+    public Class<ProfileRecord> getRecordType() {
+        return ProfileRecord.class;
+    }
+
+    /**
+     * The column <code>mccosmetics_profile.uuid</code>.
+     */
+    public final TableField<ProfileRecord, String> UUID = createField(DSL.name("uuid"), SQLDataType.CHAR(36).nullable(false), this, "");
+
+    /**
+     * The column <code>mccosmetics_profile.name</code>.
+     */
+    public final TableField<ProfileRecord, String> NAME = createField(DSL.name("name"), SQLDataType.VARCHAR(64).nullable(false), this, "");
+
+    private MccosmeticsProfile(Name alias, Table<ProfileRecord> aliased) {
+        this(alias, aliased, null);
+    }
+
+    private MccosmeticsProfile(Name alias, Table<ProfileRecord> aliased, Field<?>[] parameters) {
+        super(alias, null, aliased, parameters, DSL.comment(""), TableOptions.table());
+    }
+
+    /**
+     * Create an aliased <code>mccosmetics_profile</code> table reference
+     */
+    public MccosmeticsProfile(String alias) {
+        this(DSL.name(alias), MCCOSMETICS_PROFILE);
+    }
+
+    /**
+     * Create an aliased <code>mccosmetics_profile</code> table reference
+     */
+    public MccosmeticsProfile(Name alias) {
+        this(alias, MCCOSMETICS_PROFILE);
+    }
+
+    /**
+     * Create a <code>mccosmetics_profile</code> table reference
+     */
+    public MccosmeticsProfile() {
+        this(DSL.name("mccosmetics_profile"), null);
+    }
+
+    public <O extends Record> MccosmeticsProfile(Table<O> child, ForeignKey<O, ProfileRecord> key) {
+        super(child, key, MCCOSMETICS_PROFILE);
+    }
+
+    @Override
+    public Schema getSchema() {
+        return aliased() ? null : DefaultSchema.DEFAULT_SCHEMA;
+    }
+
+    @Override
+    public UniqueKey<ProfileRecord> getPrimaryKey() {
+        return Keys.KEY_MCCOSMETICS_PROFILE_PRIMARY;
+    }
+
+    @Override
+    public MccosmeticsProfile as(String alias) {
+        return new MccosmeticsProfile(DSL.name(alias), this);
+    }
+
+    @Override
+    public MccosmeticsProfile as(Name alias) {
+        return new MccosmeticsProfile(alias, this);
+    }
+
+    /**
+     * Rename this table
+     */
+    @Override
+    public MccosmeticsProfile rename(String name) {
+        return new MccosmeticsProfile(DSL.name(name), null);
+    }
+
+    /**
+     * Rename this table
+     */
+    @Override
+    public MccosmeticsProfile rename(Name name) {
+        return new MccosmeticsProfile(name, null);
+    }
+
+    // -------------------------------------------------------------------------
+    // Row2 type methods
+    // -------------------------------------------------------------------------
+
+    @Override
+    public Row2<String, String> fieldsRow() {
+        return (Row2) super.fieldsRow();
+    }
+}
diff --git a/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/tables/MccosmeticsProfileEquipped.java b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/tables/MccosmeticsProfileEquipped.java
new file mode 100644
index 0000000000000000000000000000000000000000..bafb667271ac8534b7dfe1150f4d6e00237879ef
--- /dev/null
+++ b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/tables/MccosmeticsProfileEquipped.java
@@ -0,0 +1,174 @@
+/*
+ * This file is generated by jOOQ.
+ */
+package io.lumine.cosmetics.storage.sql.mappings.tables;
+
+
+import io.lumine.cosmetics.storage.sql.mappings.DefaultSchema;
+import io.lumine.cosmetics.storage.sql.mappings.Indexes;
+import io.lumine.cosmetics.storage.sql.mappings.Keys;
+import io.lumine.cosmetics.storage.sql.mappings.tables.records.ProfileEquippedRecord;
+
+import java.util.Arrays;
+import java.util.List;
+
+import io.lumine.utils.lib.jooq.Field;
+import io.lumine.utils.lib.jooq.ForeignKey;
+import io.lumine.utils.lib.jooq.Index;
+import io.lumine.utils.lib.jooq.Name;
+import io.lumine.utils.lib.jooq.Record;
+import io.lumine.utils.lib.jooq.Row4;
+import io.lumine.utils.lib.jooq.Schema;
+import io.lumine.utils.lib.jooq.Table;
+import io.lumine.utils.lib.jooq.TableField;
+import io.lumine.utils.lib.jooq.TableOptions;
+import io.lumine.utils.lib.jooq.UniqueKey;
+import io.lumine.utils.lib.jooq.impl.DSL;
+import io.lumine.utils.lib.jooq.impl.SQLDataType;
+import io.lumine.utils.lib.jooq.impl.TableImpl;
+
+
+/**
+ * This class is generated by jOOQ.
+ */
+@SuppressWarnings({ "all", "unchecked", "rawtypes" })
+public class MccosmeticsProfileEquipped extends TableImpl<ProfileEquippedRecord> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * The reference instance of <code>mccosmetics_profile_equipped</code>
+     */
+    public static final MccosmeticsProfileEquipped MCCOSMETICS_PROFILE_EQUIPPED = new MccosmeticsProfileEquipped();
+
+    /**
+     * The class holding records for this type
+     */
+    @Override
+    public Class<ProfileEquippedRecord> getRecordType() {
+        return ProfileEquippedRecord.class;
+    }
+
+    /**
+     * The column <code>mccosmetics_profile_equipped.profile_uuid</code>.
+     */
+    public final TableField<ProfileEquippedRecord, String> PROFILE_UUID = createField(DSL.name("profile_uuid"), SQLDataType.CHAR(36).nullable(false), this, "");
+
+    /**
+     * The column <code>mccosmetics_profile_equipped.slot</code>.
+     */
+    public final TableField<ProfileEquippedRecord, String> SLOT = createField(DSL.name("slot"), SQLDataType.VARCHAR(32).nullable(false), this, "");
+
+    /**
+     * The column <code>mccosmetics_profile_equipped.cosmetic_id</code>.
+     */
+    public final TableField<ProfileEquippedRecord, String> COSMETIC_ID = createField(DSL.name("cosmetic_id"), SQLDataType.VARCHAR(64).nullable(false), this, "");
+
+    /**
+     * The column <code>mccosmetics_profile_equipped.cosmetic_data</code>.
+     */
+    public final TableField<ProfileEquippedRecord, String> COSMETIC_DATA = createField(DSL.name("cosmetic_data"), SQLDataType.VARCHAR(128).defaultValue(DSL.inline("NULL", SQLDataType.VARCHAR)), this, "");
+
+    private MccosmeticsProfileEquipped(Name alias, Table<ProfileEquippedRecord> aliased) {
+        this(alias, aliased, null);
+    }
+
+    private MccosmeticsProfileEquipped(Name alias, Table<ProfileEquippedRecord> aliased, Field<?>[] parameters) {
+        super(alias, null, aliased, parameters, DSL.comment(""), TableOptions.table());
+    }
+
+    /**
+     * Create an aliased <code>mccosmetics_profile_equipped</code> table
+     * reference
+     */
+    public MccosmeticsProfileEquipped(String alias) {
+        this(DSL.name(alias), MCCOSMETICS_PROFILE_EQUIPPED);
+    }
+
+    /**
+     * Create an aliased <code>mccosmetics_profile_equipped</code> table
+     * reference
+     */
+    public MccosmeticsProfileEquipped(Name alias) {
+        this(alias, MCCOSMETICS_PROFILE_EQUIPPED);
+    }
+
+    /**
+     * Create a <code>mccosmetics_profile_equipped</code> table reference
+     */
+    public MccosmeticsProfileEquipped() {
+        this(DSL.name("mccosmetics_profile_equipped"), null);
+    }
+
+    public <O extends Record> MccosmeticsProfileEquipped(Table<O> child, ForeignKey<O, ProfileEquippedRecord> key) {
+        super(child, key, MCCOSMETICS_PROFILE_EQUIPPED);
+    }
+
+    @Override
+    public Schema getSchema() {
+        return aliased() ? null : DefaultSchema.DEFAULT_SCHEMA;
+    }
+
+    @Override
+    public List<Index> getIndexes() {
+        return Arrays.asList(Indexes.MCCOSMETICS_PROFILE_EQUIPPED_MCCOSMETICS_PROFILE_EQUIPPED_COSMETIC_ID_INDEX);
+    }
+
+    @Override
+    public UniqueKey<ProfileEquippedRecord> getPrimaryKey() {
+        return Keys.KEY_MCCOSMETICS_PROFILE_EQUIPPED_PRIMARY;
+    }
+
+    @Override
+    public List<ForeignKey<ProfileEquippedRecord, ?>> getReferences() {
+        return Arrays.asList(Keys.MCCOSMETICS_PROFILE_EQUIPPED_PROFILE_FK);
+    }
+
+    private transient MccosmeticsProfile _mccosmeticsProfile;
+
+    /**
+     * Get the implicit join path to the
+     * <code>mythiccraft_test_mccosmetics.mccosmetics_profile</code> table.
+     */
+    public MccosmeticsProfile mccosmeticsProfile() {
+        if (_mccosmeticsProfile == null)
+            _mccosmeticsProfile = new MccosmeticsProfile(this, Keys.MCCOSMETICS_PROFILE_EQUIPPED_PROFILE_FK);
+
+        return _mccosmeticsProfile;
+    }
+
+    @Override
+    public MccosmeticsProfileEquipped as(String alias) {
+        return new MccosmeticsProfileEquipped(DSL.name(alias), this);
+    }
+
+    @Override
+    public MccosmeticsProfileEquipped as(Name alias) {
+        return new MccosmeticsProfileEquipped(alias, this);
+    }
+
+    /**
+     * Rename this table
+     */
+    @Override
+    public MccosmeticsProfileEquipped rename(String name) {
+        return new MccosmeticsProfileEquipped(DSL.name(name), null);
+    }
+
+    /**
+     * Rename this table
+     */
+    @Override
+    public MccosmeticsProfileEquipped rename(Name name) {
+        return new MccosmeticsProfileEquipped(name, null);
+    }
+
+    // -------------------------------------------------------------------------
+    // Row4 type methods
+    // -------------------------------------------------------------------------
+
+    @Override
+    public Row4<String, String, String, String> fieldsRow() {
+        return (Row4) super.fieldsRow();
+    }
+}
diff --git a/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/tables/records/ProfileEquippedRecord.java b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/tables/records/ProfileEquippedRecord.java
new file mode 100644
index 0000000000000000000000000000000000000000..a8be479e38e81c414e65928653fb13ece0f284db
--- /dev/null
+++ b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/tables/records/ProfileEquippedRecord.java
@@ -0,0 +1,218 @@
+/*
+ * This file is generated by jOOQ.
+ */
+package io.lumine.cosmetics.storage.sql.mappings.tables.records;
+
+
+import io.lumine.cosmetics.storage.sql.mappings.tables.MccosmeticsProfileEquipped;
+
+import io.lumine.utils.lib.jooq.Field;
+import io.lumine.utils.lib.jooq.Record2;
+import io.lumine.utils.lib.jooq.Record4;
+import io.lumine.utils.lib.jooq.Row4;
+import io.lumine.utils.lib.jooq.impl.UpdatableRecordImpl;
+
+
+/**
+ * This class is generated by jOOQ.
+ */
+@SuppressWarnings({ "all", "unchecked", "rawtypes" })
+public class ProfileEquippedRecord extends UpdatableRecordImpl<ProfileEquippedRecord> implements Record4<String, String, String, String> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Setter for <code>mccosmetics_profile_equipped.profile_uuid</code>.
+     */
+    public void setProfileUuid(String value) {
+        set(0, value);
+    }
+
+    /**
+     * Getter for <code>mccosmetics_profile_equipped.profile_uuid</code>.
+     */
+    public String getProfileUuid() {
+        return (String) get(0);
+    }
+
+    /**
+     * Setter for <code>mccosmetics_profile_equipped.slot</code>.
+     */
+    public void setSlot(String value) {
+        set(1, value);
+    }
+
+    /**
+     * Getter for <code>mccosmetics_profile_equipped.slot</code>.
+     */
+    public String getSlot() {
+        return (String) get(1);
+    }
+
+    /**
+     * Setter for <code>mccosmetics_profile_equipped.cosmetic_id</code>.
+     */
+    public void setCosmeticId(String value) {
+        set(2, value);
+    }
+
+    /**
+     * Getter for <code>mccosmetics_profile_equipped.cosmetic_id</code>.
+     */
+    public String getCosmeticId() {
+        return (String) get(2);
+    }
+
+    /**
+     * Setter for <code>mccosmetics_profile_equipped.cosmetic_data</code>.
+     */
+    public void setCosmeticData(String value) {
+        set(3, value);
+    }
+
+    /**
+     * Getter for <code>mccosmetics_profile_equipped.cosmetic_data</code>.
+     */
+    public String getCosmeticData() {
+        return (String) get(3);
+    }
+
+    // -------------------------------------------------------------------------
+    // Primary key information
+    // -------------------------------------------------------------------------
+
+    @Override
+    public Record2<String, String> key() {
+        return (Record2) super.key();
+    }
+
+    // -------------------------------------------------------------------------
+    // Record4 type implementation
+    // -------------------------------------------------------------------------
+
+    @Override
+    public Row4<String, String, String, String> fieldsRow() {
+        return (Row4) super.fieldsRow();
+    }
+
+    @Override
+    public Row4<String, String, String, String> valuesRow() {
+        return (Row4) super.valuesRow();
+    }
+
+    @Override
+    public Field<String> field1() {
+        return MccosmeticsProfileEquipped.MCCOSMETICS_PROFILE_EQUIPPED.PROFILE_UUID;
+    }
+
+    @Override
+    public Field<String> field2() {
+        return MccosmeticsProfileEquipped.MCCOSMETICS_PROFILE_EQUIPPED.SLOT;
+    }
+
+    @Override
+    public Field<String> field3() {
+        return MccosmeticsProfileEquipped.MCCOSMETICS_PROFILE_EQUIPPED.COSMETIC_ID;
+    }
+
+    @Override
+    public Field<String> field4() {
+        return MccosmeticsProfileEquipped.MCCOSMETICS_PROFILE_EQUIPPED.COSMETIC_DATA;
+    }
+
+    @Override
+    public String component1() {
+        return getProfileUuid();
+    }
+
+    @Override
+    public String component2() {
+        return getSlot();
+    }
+
+    @Override
+    public String component3() {
+        return getCosmeticId();
+    }
+
+    @Override
+    public String component4() {
+        return getCosmeticData();
+    }
+
+    @Override
+    public String value1() {
+        return getProfileUuid();
+    }
+
+    @Override
+    public String value2() {
+        return getSlot();
+    }
+
+    @Override
+    public String value3() {
+        return getCosmeticId();
+    }
+
+    @Override
+    public String value4() {
+        return getCosmeticData();
+    }
+
+    @Override
+    public ProfileEquippedRecord value1(String value) {
+        setProfileUuid(value);
+        return this;
+    }
+
+    @Override
+    public ProfileEquippedRecord value2(String value) {
+        setSlot(value);
+        return this;
+    }
+
+    @Override
+    public ProfileEquippedRecord value3(String value) {
+        setCosmeticId(value);
+        return this;
+    }
+
+    @Override
+    public ProfileEquippedRecord value4(String value) {
+        setCosmeticData(value);
+        return this;
+    }
+
+    @Override
+    public ProfileEquippedRecord values(String value1, String value2, String value3, String value4) {
+        value1(value1);
+        value2(value2);
+        value3(value3);
+        value4(value4);
+        return this;
+    }
+
+    // -------------------------------------------------------------------------
+    // Constructors
+    // -------------------------------------------------------------------------
+
+    /**
+     * Create a detached MccosmeticsProfileEquippedRecord
+     */
+    public ProfileEquippedRecord() {
+        super(MccosmeticsProfileEquipped.MCCOSMETICS_PROFILE_EQUIPPED);
+    }
+
+    /**
+     * Create a detached, initialised MccosmeticsProfileEquippedRecord
+     */
+    public ProfileEquippedRecord(String profileUuid, String slot, String cosmeticId, String cosmeticData) {
+        super(MccosmeticsProfileEquipped.MCCOSMETICS_PROFILE_EQUIPPED);
+
+        setProfileUuid(profileUuid);
+        setSlot(slot);
+        setCosmeticId(cosmeticId);
+        setCosmeticData(cosmeticData);
+    }
+}
diff --git a/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/tables/records/ProfileRecord.java b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/tables/records/ProfileRecord.java
new file mode 100644
index 0000000000000000000000000000000000000000..97980afd0bb92524bb17b270d125b642f3d6cbf0
--- /dev/null
+++ b/plugin/src/main/java/io/lumine/cosmetics/storage/sql/mappings/tables/records/ProfileRecord.java
@@ -0,0 +1,144 @@
+/*
+ * This file is generated by jOOQ.
+ */
+package io.lumine.cosmetics.storage.sql.mappings.tables.records;
+
+
+import io.lumine.cosmetics.storage.sql.mappings.tables.MccosmeticsProfile;
+
+import io.lumine.utils.lib.jooq.Field;
+import io.lumine.utils.lib.jooq.Record1;
+import io.lumine.utils.lib.jooq.Record2;
+import io.lumine.utils.lib.jooq.Row2;
+import io.lumine.utils.lib.jooq.impl.UpdatableRecordImpl;
+
+
+/**
+ * This class is generated by jOOQ.
+ */
+@SuppressWarnings({ "all", "unchecked", "rawtypes" })
+public class ProfileRecord extends UpdatableRecordImpl<ProfileRecord> implements Record2<String, String> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Setter for <code>mccosmetics_profile.uuid</code>.
+     */
+    public void setUuid(String value) {
+        set(0, value);
+    }
+
+    /**
+     * Getter for <code>mccosmetics_profile.uuid</code>.
+     */
+    public String getUuid() {
+        return (String) get(0);
+    }
+
+    /**
+     * Setter for <code>mccosmetics_profile.name</code>.
+     */
+    public void setName(String value) {
+        set(1, value);
+    }
+
+    /**
+     * Getter for <code>mccosmetics_profile.name</code>.
+     */
+    public String getName() {
+        return (String) get(1);
+    }
+
+    // -------------------------------------------------------------------------
+    // Primary key information
+    // -------------------------------------------------------------------------
+
+    @Override
+    public Record1<String> key() {
+        return (Record1) super.key();
+    }
+
+    // -------------------------------------------------------------------------
+    // Record2 type implementation
+    // -------------------------------------------------------------------------
+
+    @Override
+    public Row2<String, String> fieldsRow() {
+        return (Row2) super.fieldsRow();
+    }
+
+    @Override
+    public Row2<String, String> valuesRow() {
+        return (Row2) super.valuesRow();
+    }
+
+    @Override
+    public Field<String> field1() {
+        return MccosmeticsProfile.MCCOSMETICS_PROFILE.UUID;
+    }
+
+    @Override
+    public Field<String> field2() {
+        return MccosmeticsProfile.MCCOSMETICS_PROFILE.NAME;
+    }
+
+    @Override
+    public String component1() {
+        return getUuid();
+    }
+
+    @Override
+    public String component2() {
+        return getName();
+    }
+
+    @Override
+    public String value1() {
+        return getUuid();
+    }
+
+    @Override
+    public String value2() {
+        return getName();
+    }
+
+    @Override
+    public ProfileRecord value1(String value) {
+        setUuid(value);
+        return this;
+    }
+
+    @Override
+    public ProfileRecord value2(String value) {
+        setName(value);
+        return this;
+    }
+
+    @Override
+    public ProfileRecord values(String value1, String value2) {
+        value1(value1);
+        value2(value2);
+        return this;
+    }
+
+    // -------------------------------------------------------------------------
+    // Constructors
+    // -------------------------------------------------------------------------
+
+    /**
+     * Create a detached MccosmeticsProfileRecord
+     */
+    public ProfileRecord() {
+        super(MccosmeticsProfile.MCCOSMETICS_PROFILE);
+    }
+
+    /**
+     * Create a detached, initialised MccosmeticsProfileRecord
+     */
+    public ProfileRecord(String uuid, String name) {
+        super(MccosmeticsProfile.MCCOSMETICS_PROFILE);
+
+        setUuid(uuid);
+        setName(name);
+    }
+}
diff --git a/pom.xml b/pom.xml
index 30aca0771e6e43f505cf6676a2dc7a741a28545d..0b53cd042f0be135a791c2c7967c3322fe557511 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
     </organization>  
   
 	<properties>  
-	    <mccosmetics.version>0.7.0-SNAPSHOT</mccosmetics.version>
+	    <mccosmetics.version>0.8.0-SNAPSHOT</mccosmetics.version>
 	    <paperapi.version>1.19-R0.1-SNAPSHOT</paperapi.version>
 	    <lumineutils.version>1.18-SNAPSHOT</lumineutils.version>
 	    <lombok.version>1.18.22</lombok.version>
diff --git a/sql/.gitignore b/sql/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..e3425b9cc114cdcb390fb9c7201b1ffdce23d875
--- /dev/null
+++ b/sql/.gitignore
@@ -0,0 +1 @@
+/.flattened-pom.xml
diff --git a/sql/pom.xml b/sql/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7df4e48b199f12faea58f4ed2ded85e7895210da
--- /dev/null
+++ b/sql/pom.xml
@@ -0,0 +1,120 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>MCCosmetics-SQL</artifactId>
+    <parent> 
+        <groupId>io.lumine</groupId>
+        <artifactId>MCCosmetics-Plugin</artifactId>
+        <version>${mccosmetics.version}</version>
+    </parent>  
+ 
+    <pluginRepositories>
+        <pluginRepository>
+            <id>maven-snapshots</id>
+            <url>https://repository.apache.org/content/repositories/snapshots/</url>
+        </pluginRepository>
+    </pluginRepositories>
+
+    <dependencies>
+        <dependency> 
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>${lombok.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mariadb.jdbc</groupId>
+            <artifactId>mariadb-java-client</artifactId>
+            <version>2.1.2</version>
+        </dependency>
+        <!-- Spigot API -->
+        <dependency>
+            <groupId>io.papermc.paper</groupId>
+            <artifactId>paper-api</artifactId>
+            <version>${paperapi.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jooq</groupId>
+            <artifactId>jooq</artifactId>
+            <version>3.8.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jooq</groupId>
+            <artifactId>jooq-meta</artifactId>
+            <version>3.8.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jooq</groupId>
+            <artifactId>jooq-codegen</artifactId>
+            <version>3.8.3</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.8.0</version>
+                <executions>
+                    <execution>
+                        <id>default-compile</id>
+                        <configuration>
+                            <release>16</release>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.jooq</groupId>
+                <artifactId>jooq-codegen-maven</artifactId>
+                <version>3.16.0</version>
+            
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            
+                <dependencies>
+                    <dependency>
+                        <groupId>mysql</groupId>
+                        <artifactId>mysql-connector-java</artifactId>
+                        <version>6.0.3</version>
+                    </dependency>
+                </dependencies>
+            
+                <configuration>
+             
+                    <jdbc>
+                        <driver>org.mariadb.jdbc.Driver</driver>
+                        <url>jdbc:mariadb://localhost:3306/mythiccraft_test_mccosmetics</url>
+                        <user>mythiccraft_tester</user>
+                        <password>62e06d5e-6c48-4c40-a070-00949d2a9c6a</password>
+                    </jdbc>
+            
+                    <generator>
+                        <database>
+                            <name>org.jooq.meta.mysql.MySQLDatabase</name>
+                            <includes>.*</includes>
+                            <excludes></excludes>
+                            <schemata>
+                                <schema>
+                                    <inputSchema>mythiccraft_test_mccosmetics</inputSchema>
+                                    <outputSchemaToDefault>true</outputSchemaToDefault>
+                                </schema>
+                            </schemata>
+                        </database>
+                        <target>
+                            <packageName>io.lumine.cosmetics.storage.sql.mappings</packageName>
+                            <directory>../plugin/src/main/java</directory>
+                        </target>
+                    </generator>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <packaging>pom</packaging>
+</project>
\ No newline at end of file
diff --git a/sql/src/main/java/io/lumine/achievements/sql/CarsonJF.java b/sql/src/main/java/io/lumine/achievements/sql/CarsonJF.java
new file mode 100644
index 0000000000000000000000000000000000000000..c7eab5c0a7563bfdaa877ab549fa0aa6ea40c1a9
--- /dev/null
+++ b/sql/src/main/java/io/lumine/achievements/sql/CarsonJF.java
@@ -0,0 +1,5 @@
+package io.lumine.achievements.sql;
+
+public class CarsonJF {
+    // this plugin has been infected by CarsonJF
+}