Thread Tools Display Modes
11-09-20, 09:56 PM   #1
Niketa
A Wyrmkin Dreamwalker
 
Niketa's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2013
Posts: 54
AceDB help

Hi all. I'm wondering if anyone can explain the proper way to handle database restructures when using AceDB. I'm wanting to release an alpha version of an add-on I'm working on but I want to make sure stable databases are not lost. In my current development version I've restructured the database.

I am not ready to convert stable DBs into the new one yet, so the plan is to save a backup of the stable db when someone uses the alpha. However I want to be able to restore the stable db if they decide they don't wanna deal with the alpha and revert back to stable.

I've managed to save a backup of the stable db fine but I'm having issues restoring it in the stable version.

I was able to have it write the user saved data, but I get errors until a reload. I think it's because I'm using "**" in my defaults DB and when I manually add the saved data it's not linked to that. I then tried to set it as a metatable but it didn't work. Then my lunch break was over so that was all I could see from there.

Anyway this whole process has just seemed way too complicated for something that was so easy before I used AceDB (save a backup and just rewrite). I'm wondering if there's something I'm missing that would make this process a lot simpler?

Or is it just because am doing the metatables wrong?

As I'm on my phone now I can't really show the code and I didn't commit it before I left but if it's needed I can show when I get home.

Issue is with the char DB. I have a table inside it called bars and then a table nested in that with the "**" key and another table inside that with another "**".

So I tried after writing the saved data to set it like

setmetatable(barrable, defaultbartable["**"])

That just being pseudocode but that was what didn't work. And I did the same with the nested "**"

Edit: this is what I've got so far, and the problem with it is that it's only saving the values for items that are in the default and not also the ones in the saved. I don't know if I'm just missing something because I'm tired or what.

Lua Code:
  1. local defaults = {
  2.         char = {
  3.             numBars = 1,
  4.             bars = {
  5.                 ["**"] = {
  6.                     enabled = false,
  7.                     desc = "",
  8.  
  9.                     movable = true,
  10.                     hidden = false,
  11.                     mouseover = false,
  12.                     anchorMouseover = false,
  13.                     showEmpties = true,
  14.  
  15.                     muteAlerts = false,
  16.                     trackProgress = false,
  17.                     trackCompletedObjectives = true,
  18.  
  19.                     visibleButtons = 6,
  20.                     direction = 2, -- 1: Up, 2: Right, 3: Down, 4: Left
  21.                     buttonsPerRow = 12,
  22.                     rowDirection = 1, -- 1: Normal (Right/Down), 2: Reverse (Left/Up)
  23.  
  24.                     alpha = 1,
  25.                     scale = 1,
  26.  
  27.                     position = {"TOP"},
  28.  
  29.                     buttonSize = 35,
  30.                     buttonPadding = 2,
  31.  
  32.                     font = {
  33.                         face = false,
  34.                         outline = false,
  35.                         size = false,
  36.                     },
  37.  
  38.                     count = {
  39.                         anchor = "BOTTOM",
  40.                         xOffset = 1,
  41.                         yOffset = 6,
  42.                     },
  43.  
  44.                     objective = {
  45.                         anchor = "TOPLEFT",
  46.                         xOffset = 6,
  47.                         yOffset = -4,
  48.                     },
  49.  
  50.                     objectives = {
  51.                         ["**"] = {
  52.                             objective = false,
  53.                         },
  54.                     },
  55.                 },
  56.             },
  57.         },
  58.         global = {
  59.             autoLootItems = false,
  60.             alerts = {
  61.                 barChat = true,
  62.                 barScreen = true,
  63.                 barSound = true,
  64.                 chat = true,
  65.                 screen = true,
  66.                 sound = true,
  67.             },
  68.             alertFormats = {
  69.                 objectivePreview = 200,
  70.                 newCountPreview = 25,
  71.                 oldCountPreview = 20,
  72.                 barCountPreview = 1,
  73.                 barTotalPreview = 5,
  74.                 barTitlePreview = true,
  75.  
  76.                 barProgress = self.barProgress,
  77.                 hasObjective = self.hasObjective,
  78.                 noObjective = self.noObjective,
  79.             },
  80.             commands = {
  81.                 farmbar = true,
  82.                 farm = true,
  83.                 fbar = true,
  84.                 fb = false,
  85.             },
  86.             sounds = {
  87.                 barProgress = "Auction Open",
  88.                 barComplete = "Auction Close",
  89.                 farmingProgress = "Loot Coin",
  90.                 objectiveComplete = "Quest Complete",
  91.                 objectiveSet = "Quest Activate",
  92.                 objectiveCleared = "Quest Failed",
  93.             },
  94.             template = {
  95.                 includeData = false,
  96.                 includeDataPrompt = false,
  97.                 saveOrder = false,
  98.                 saveOrderPrompt = false,
  99.             },
  100.             tooltips = {
  101.                 bar = true,
  102.                 barTips = true,
  103.                 button = true,
  104.                 buttonTips = true,
  105.                 enableMod = true,
  106.                 mod = "Alt",
  107.             },
  108.             skins = {},
  109.             templates = {},
  110.             version = 2,
  111.         },
  112.         profile = {
  113.             style = {
  114.                 font = {
  115.                     face = "Friz Quadrata TT",
  116.                     outline = "OUTLINE",
  117.                     size = 11,
  118.                 },
  119.                 skin = {
  120.                     type = "builtin",
  121.                     name = "default",
  122.                 },
  123.                 layers = {
  124.                     AutoCastable = true, -- bank overlay
  125.                     Border = false, -- oGlow
  126.                     Cooldown = false,
  127.                     CooldownEdge = false,
  128.                 },
  129.                 count = {
  130.                     type = "custom", -- "includeBank", "oGlow", "custom"
  131.                     color = {1, 1, 1, 1},
  132.                 },
  133.             },
  134.         },
  135.     }
  136.  
  137.     local backup = {}
  138.     local version3 = FarmingBarDB and FarmingBarDB.global.version == 3
  139.     if version3 then
  140.         for k, v in pairs(FarmingBarDB) do
  141.             backup[k] = v
  142.         end
  143.         wipe(FarmingBarDB)
  144.     end
  145.  
  146.     self.db = LibStub("AceDB-3.0"):New(addonName .. "DB", defaults, true)
  147.  
  148.     if version3 then
  149.         local version2 = backup.global.version2
  150.         if version2 then
  151.             if version2.global then
  152.                 for k, v in pairs(version2.global) do
  153.                     self.db.global[k] = v
  154.                 end
  155.             end
  156.  
  157.             if version2.profile then
  158.                 for k, v in pairs(version2.profile) do
  159.                     self.db.profile[k] = v
  160.                 end
  161.             end
  162.  
  163.             if version2.char then
  164.                 local realmKey = GetRealmName()
  165.                 local charKey = UnitName("player").." - "..realmKey
  166.                 local defaultBar = defaults.char.bars["**"]
  167.                 if version2.char[charKey] then
  168.                     local char = version2.char[charKey]
  169.                     self.db.char.numBars = char.numBars or defaults.char.numBars
  170.                     for k, v in pairs(defaultBar) do
  171.                         for barID, bar in pairs(char.bars) do
  172.                             if k == "objectives" then
  173.                                 for objectiveID, objective in pairs(bar.objectives) do
  174.                                     for K, V in pairs(defaultBar.objectives["**"]) do
  175.                                         C_Timer.After(5, function()
  176.                                             print(K, V)
  177.                                         end)
  178.                                         self.db.char.bars[barID].objectives[objectiveID][K] = (objective[K] ~= nil and objective[K]) or V
  179.                                     end
  180.                                 end
  181.                             else
  182.                                 self.db.char.bars[barID][k] = (bar[k] ~= nil and bar[k]) or v
  183.                             end
  184.                         end
  185.                     end
  186.                 end
  187.             end
  188.         end
  189.     end

Seeing as I've had no responses so far and I've come up with something that... works, I'll post it here in case it helps anyone else. But I still wonder if there's a better way to do this. I feel like this solution is a bit messy (but also it's just a quick fix to a temporary problem anyway so I'm not that concerned).

Lua Code:
  1. local defaults = {
  2.         char = {
  3.             numBars = 1,
  4.             bars = {
  5.                 ["**"] = {
  6.                     enabled = false,
  7.                     desc = "",
  8.  
  9.                     movable = true,
  10.                     hidden = false,
  11.                     mouseover = false,
  12.                     anchorMouseover = false,
  13.                     showEmpties = true,
  14.  
  15.                     muteAlerts = false,
  16.                     trackProgress = false,
  17.                     trackCompletedObjectives = true,
  18.  
  19.                     visibleButtons = 6,
  20.                     direction = 2, -- 1: Up, 2: Right, 3: Down, 4: Left
  21.                     buttonsPerRow = 12,
  22.                     rowDirection = 1, -- 1: Normal (Right/Down), 2: Reverse (Left/Up)
  23.  
  24.                     alpha = 1,
  25.                     scale = 1,
  26.  
  27.                     position = {"TOP"},
  28.  
  29.                     buttonSize = 35,
  30.                     buttonPadding = 2,
  31.  
  32.                     font = {
  33.                         face = false,
  34.                         outline = false,
  35.                         size = false,
  36.                     },
  37.  
  38.                     count = {
  39.                         anchor = "BOTTOM",
  40.                         xOffset = 1,
  41.                         yOffset = 6,
  42.                     },
  43.  
  44.                     objective = {
  45.                         anchor = "TOPLEFT",
  46.                         xOffset = 6,
  47.                         yOffset = -4,
  48.                     },
  49.  
  50.                     objectives = {
  51.                         ["**"] = {
  52.                             objective = false,
  53.                         },
  54.                     },
  55.                 },
  56.             },
  57.         },
  58.         global = {
  59.             autoLootItems = false,
  60.             alerts = {
  61.                 barChat = true,
  62.                 barScreen = true,
  63.                 barSound = true,
  64.                 chat = true,
  65.                 screen = true,
  66.                 sound = true,
  67.             },
  68.             alertFormats = {
  69.                 objectivePreview = 200,
  70.                 newCountPreview = 25,
  71.                 oldCountPreview = 20,
  72.                 barCountPreview = 1,
  73.                 barTotalPreview = 5,
  74.                 barTitlePreview = true,
  75.  
  76.                 barProgress = self.barProgress,
  77.                 hasObjective = self.hasObjective,
  78.                 noObjective = self.noObjective,
  79.             },
  80.             commands = {
  81.                 farmbar = true,
  82.                 farm = true,
  83.                 fbar = true,
  84.                 fb = false,
  85.             },
  86.             sounds = {
  87.                 barProgress = "Auction Open",
  88.                 barComplete = "Auction Close",
  89.                 farmingProgress = "Loot Coin",
  90.                 objectiveComplete = "Quest Complete",
  91.                 objectiveSet = "Quest Activate",
  92.                 objectiveCleared = "Quest Failed",
  93.             },
  94.             template = {
  95.                 includeData = false,
  96.                 includeDataPrompt = false,
  97.                 saveOrder = false,
  98.                 saveOrderPrompt = false,
  99.             },
  100.             tooltips = {
  101.                 bar = true,
  102.                 barTips = true,
  103.                 button = true,
  104.                 buttonTips = true,
  105.                 enableMod = true,
  106.                 mod = "Alt",
  107.             },
  108.             skins = {},
  109.             templates = {},
  110.             version = 2,
  111.         },
  112.         profile = {
  113.             style = {
  114.                 font = {
  115.                     face = "Friz Quadrata TT",
  116.                     outline = "OUTLINE",
  117.                     size = 11,
  118.                 },
  119.                 skin = {
  120.                     type = "builtin",
  121.                     name = "default",
  122.                 },
  123.                 layers = {
  124.                     AutoCastable = true, -- bank overlay
  125.                     Border = false, -- oGlow
  126.                     Cooldown = false,
  127.                     CooldownEdge = false,
  128.                 },
  129.                 count = {
  130.                     type = "custom", -- "includeBank", "oGlow", "custom"
  131.                     color = {1, 1, 1, 1},
  132.                 },
  133.             },
  134.         },
  135.     }
  136.  
  137.     ------------------------------------------------------------
  138.  
  139.     -- If coming back from version 3, save data to backup and wipe FarmingBarDB to prevent lua errors from changed k/v
  140.     -- Don't wipe the whole DB as it'll wipe profiles and profileKeys
  141.     local backup, version2 = {}
  142.     if FarmingBarDB then
  143.         version2 = FarmingBarDB.global and FarmingBarDB.global.version2
  144.         if version2 then
  145.             for k, v in pairs(version2) do
  146.                 backup[k] = v
  147.             end
  148.             FarmingBarDB.char = nil
  149.             FarmingBarDB.global = nil
  150.             FarmingBarDB.profile = nil
  151.         end
  152.     end
  153.  
  154.     ------------------------------------------------------------
  155.  
  156.     self.db = LibStub("AceDB-3.0"):New(addonName .. "DB", defaults, true)
  157.  
  158.     ------------------------------------------------------------
  159.  
  160.     -- Save the backup to the database, so we can still access multiple characters' saved data
  161.     -- We'll delete as we go below
  162.     if version2 then
  163.         self.db.global.version2_2 = backup
  164.     end
  165.  
  166.     local version2_2 = self.db.global.version2_2
  167.     if version2_2 then
  168.         -- Copy profiles and delete; no use for this after the first time
  169.         if version2_2.profiles then
  170.             for k, v in pairs(version2_2.profiles) do
  171.                 self.db.profiles[k] = v
  172.             end
  173.             self.db.global.version2_2.profiles = nil
  174.         end
  175.  
  176.         -- Copy global and delete; no use for this after the first time
  177.         if version2_2.global then
  178.             for k, v in pairs(version2_2.global) do
  179.                 self.db.global[k] = v
  180.             end
  181.             self.db.global.version2_2.global = nil
  182.         end
  183.         if version2_2.profile then
  184.             for k, v in pairs(version2_2.profile) do
  185.                 self.db.profile[k] = v
  186.             end
  187.             self.db.global.version2_2.profile = nil
  188.         end
  189.  
  190.         ------------------------------------------------------------
  191.  
  192.         -- If there's a saved char db for the current toon, copy and delete
  193.         local realmKey = GetRealmName()
  194.         local charKey = UnitName("player").." - "..realmKey
  195.         if version2_2.char then
  196.             local char = version2_2.char[charKey]
  197.             if char then
  198.                 -- Set the data
  199.                 self.db.char.numBars = char.numBars
  200.                 for k, v in pairs(char.bars) do
  201.                     tinsert(self.db.char.bars, v)
  202.                 end
  203.  
  204.                 -- Remove from the backup
  205.                 self.db.global.version2_2.char[charKey] = nil
  206.                 if U.tcount(version2_2.char) == 0 then
  207.                     self.db.global.version2_2.char = nil
  208.                 end
  209.  
  210.                 -- Calling this ensures the new bars have the correct metatables set
  211.                 self:OnInitialize()
  212.                 return
  213.             end
  214.         end
  215.  
  216.         -- If we have backup profileKeys for this character, change the profile to the correct profile and remove
  217.         if version2_2.profileKeys and version2_2.profileKeys[charKey] then
  218.             self.db:SetProfile(version2_2.profileKeys[charKey])
  219.  
  220.             version2_2.profileKeys[charKey] = nil
  221.             if U.tcount(version2_2.profileKeys) == 0 then
  222.                 self.db.global.version2_2.profileKeys = nil
  223.             end
  224.         end
  225.  
  226.         ------------------------------------------------------------
  227.  
  228.         -- If there are no more items in the backup, remove the backup
  229.         if U.tcount(version2_2) == 0 then
  230.             self.db.global.version2_2 = nil
  231.         end
  232.     end

Last edited by Niketa : 11-12-20 at 09:30 AM. Reason: Added "solution"
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » AceDB help

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off