1 --- **AceDB-3.0** manages the SavedVariables of your addon.
2 -- It offers profile management, smart defaults and namespaces for modules.\\
3 -- Data can be saved in different data-types, depending on its intended usage.
4 -- The most common data-type is the `profile` type, which allows the user to choose
5 -- the active profile, and manage the profiles of all of his characters.\\
6 -- The following data types are available:
7 -- * **char** Character-specific data. Every character has its own database.
8 -- * **realm** Realm-specific data. All of the players characters on the same realm share this database.
9 -- * **class** Class-specific data. All of the players characters of the same class share this database.
10 -- * **race** Race-specific data. All of the players characters of the same race share this database.
11 -- * **faction** Faction-specific data. All of the players characters of the same faction share this database.
12 -- * **factionrealm** Faction and realm specific data. All of the players characters on the same realm and of the same faction share this database.
13 -- * **global** Global Data. All characters on the same account share this database.
14 -- * **profile** Profile-specific data. All characters using the same profile share this database. The user can control which profile should be used.
16 -- Creating a new Database using the `:New` function will return a new DBObject. A database will inherit all functions
17 -- of the DBObjectLib listed here. \\
18 -- If you create a new namespaced child-database (`:RegisterNamespace`), you'll get a DBObject as well, but note
19 -- that the child-databases cannot individually change their profile, and are linked to their parents profile - and because of that,
20 -- the profile related APIs are not available. Only `:RegisterDefaults` and `:ResetProfile` are available on child-databases.
22 -- For more details on how to use AceDB-3.0, see the [[AceDB-3.0 Tutorial]].
24 -- You may also be interested in [[libdualspec-1-0|LibDualSpec-1.0]] to do profile switching automatically when switching specs.
27 -- MyAddon = LibStub("AceAddon-3.0"):NewAddon("DBExample")
29 -- -- declare defaults to be used in the DB
36 -- function MyAddon:OnInitialize()
37 -- -- Assuming the .toc says ## SavedVariables: MyAddonDB
38 -- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
41 -- @name AceDB-3.0.lua
42 -- @release $Id: AceDB-3.0.lua 1111 2014-07-19 20:01:42Z kaelten $
43 local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 24
44 local AceDB, oldminor = LibStub:NewLibrary(ACEDB_MAJOR, ACEDB_MINOR)
46 if not AceDB then return end -- No upgrade needed
49 local type, pairs, next, error = type, pairs, next, error
50 local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
55 -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
56 -- List them here for Mikk's FindGlobals script
59 AceDB.db_registry = AceDB.db_registry or {}
60 AceDB.frame = AceDB.frame or CreateFrame("Frame")
63 local CallbackDummy = { Fire = function() end }
65 local DBObjectLib = {}
67 --[[-------------------------------------------------------------------------
68 AceDB Utility Functions
69 ---------------------------------------------------------------------------]]
71 -- Simple shallow copy for copying defaults
72 local function copyTable(src, dest)
73 if type(dest) ~= "table" then dest = {} end
74 if type(src) == "table" then
75 for k,v in pairs(src) do
76 if type(v) == "table" then
77 -- try to index the key first so that the metatable creates the defaults, if set, and use that table
78 v = copyTable(v, dest[k])
86 -- Called to add defaults to a section of the database
88 -- When a ["*"] default section is indexed with a new key, a table is returned
89 -- and set in the host table. These tables must be cleaned up by removeDefaults
90 -- in order to ensure we don't write empty default tables.
91 local function copyDefaults(dest, src)
92 -- this happens if some value in the SV overwrites our default value with a non-table
93 --if type(dest) ~= "table" then return end
94 for k, v in pairs(src) do
95 if k == "*" or k == "**" then
96 if type(v) == "table" then
97 -- This is a metatable used for table defaults
99 -- This handles the lookup and creation of new subtables
100 __index = function(t,k)
101 if k == nil then return nil end
108 setmetatable(dest, mt)
109 -- handle already existing tables in the SV
110 for dk, dv in pairs(dest) do
111 if not rawget(src, dk) and type(dv) == "table" then
116 -- Values are not tables, so this is just a simple return
117 local mt = {__index = function(t,k) return k~=nil and v or nil end}
118 setmetatable(dest, mt)
120 elseif type(v) == "table" then
121 if not rawget(dest, k) then rawset(dest, k, {}) end
122 if type(dest[k]) == "table" then
123 copyDefaults(dest[k], v)
125 copyDefaults(dest[k], src['**'])
129 if rawget(dest, k) == nil then
136 -- Called to remove all defaults in the default table from the database
137 local function removeDefaults(db, defaults, blocker)
138 -- remove all metatables from the db, so we don't accidentally create new sub-tables through them
139 setmetatable(db, nil)
140 -- loop through the defaults and remove their content
141 for k,v in pairs(defaults) do
142 if k == "*" or k == "**" then
143 if type(v) == "table" then
144 -- Loop through all the actual k,v pairs and remove
145 for key, value in pairs(db) do
146 if type(value) == "table" then
147 -- if the key was not explicitly specified in the defaults table, just strip everything from * and ** tables
148 if defaults[key] == nil and (not blocker or blocker[key] == nil) then
149 removeDefaults(value, v)
150 -- if the table is empty afterwards, remove it
151 if next(value) == nil then
154 -- if it was specified, only strip ** content, but block values which were set in the key table
155 elseif k == "**" then
156 removeDefaults(value, v, defaults[key])
161 -- check for non-table default
162 for key, value in pairs(db) do
163 if defaults[key] == nil and v == value then
168 elseif type(v) == "table" and type(db[k]) == "table" then
169 -- if a blocker was set, dive into it, to allow multi-level defaults
170 removeDefaults(db[k], v, blocker and blocker[k])
171 if next(db[k]) == nil then
175 -- check if the current value matches the default, and that its not blocked by another defaults table
176 if db[k] == defaults[k] and (not blocker or blocker[k] == nil) then
183 -- This is called when a table section is first accessed, to set up the defaults
184 local function initSection(db, section, svstore, key, defaults)
185 local sv = rawget(db, "sv")
188 if not sv[svstore] then sv[svstore] = {} end
189 if not sv[svstore][key] then
190 sv[svstore][key] = {}
194 local tbl = sv[svstore][key]
197 copyDefaults(tbl, defaults)
199 rawset(db, section, tbl)
201 return tableCreated, tbl
204 -- Metatable to handle the dynamic creation of sections and copying of sections.
206 __index = function(t, section)
207 local keys = rawget(t, "keys")
208 local key = keys[section]
210 local defaultTbl = rawget(t, "defaults")
211 local defaults = defaultTbl and defaultTbl[section]
213 if section == "profile" then
214 local new = initSection(t, section, "profiles", key, defaults)
216 -- Callback: OnNewProfile, database, newProfileKey
217 t.callbacks:Fire("OnNewProfile", t, key)
219 elseif section == "profiles" then
220 local sv = rawget(t, "sv")
221 if not sv.profiles then sv.profiles = {} end
222 rawset(t, "profiles", sv.profiles)
223 elseif section == "global" then
224 local sv = rawget(t, "sv")
225 if not sv.global then sv.global = {} end
227 copyDefaults(sv.global, defaults)
229 rawset(t, section, sv.global)
231 initSection(t, section, section, key, defaults)
235 return rawget(t, section)
239 local function validateDefaults(defaults, keyTbl, offset)
240 if not defaults then return end
242 for k in pairs(defaults) do
243 if not keyTbl[k] or k == "profiles" then
244 error(("Usage: AceDBObject:RegisterDefaults(defaults): '%s' is not a valid datatype."):format(k), 3 + offset)
249 local preserve_keys = {
250 ["callbacks"] = true,
251 ["RegisterCallback"] = true,
252 ["UnregisterCallback"] = true,
253 ["UnregisterAllCallbacks"] = true,
257 local realmKey = GetRealmName()
258 local charKey = UnitName("player") .. " - " .. realmKey
259 local _, classKey = UnitClass("player")
260 local _, raceKey = UnitRace("player")
261 local factionKey = UnitFactionGroup("player")
262 local factionrealmKey = factionKey .. " - " .. realmKey
263 local localeKey = GetLocale():lower()
265 local regionKey = GetCVar("portal") == "public-test" and "PTR" or GetCVar("portal")
266 local factionrealmregionKey = factionrealmKey .. " - " .. regionKey
268 -- Actual database initialization function
269 local function initdb(sv, defaults, defaultProfile, olddb, parent)
270 -- Generate the database keys for each section
272 -- map "true" to our "Default" profile
273 if defaultProfile == true then defaultProfile = "Default" end
277 -- Make a container for profile keys
278 if not sv.profileKeys then sv.profileKeys = {} end
280 -- Try to get the profile selected from the char db
281 profileKey = sv.profileKeys[charKey] or defaultProfile or charKey
283 -- save the selected profile for later
284 sv.profileKeys[charKey] = profileKey
286 -- Use the profile of the parents DB
287 profileKey = parent.keys.profile or defaultProfile or charKey
289 -- clear the profileKeys in the DB, namespaces don't need to store them
293 -- This table contains keys that enable the dynamic creation
294 -- of each section of the table. The 'global' and 'profiles'
295 -- have a key of true, since they are handled in a special case
298 ["realm"] = realmKey,
299 ["class"] = classKey,
301 ["faction"] = factionKey,
302 ["factionrealm"] = factionrealmKey,
303 ["factionrealmregion"] = factionrealmregionKey,
304 ["profile"] = profileKey,
305 ["locale"] = localeKey,
310 validateDefaults(defaults, keyTbl, 1)
312 -- This allows us to use this function to reset an entire database
313 -- Clear out the old database
315 for k,v in pairs(olddb) do if not preserve_keys[k] then olddb[k] = nil end end
318 -- Give this database the metatable so it initializes dynamically
319 local db = setmetatable(olddb or {}, dbmt)
321 if not rawget(db, "callbacks") then
322 -- try to load CallbackHandler-1.0 if it loaded after our library
323 if not CallbackHandler then CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0", true) end
324 db.callbacks = CallbackHandler and CallbackHandler:New(db) or CallbackDummy
327 -- Copy methods locally into the database object, to avoid hitting
328 -- the metatable when calling methods
331 for name, func in pairs(DBObjectLib) do
336 db.RegisterDefaults = DBObjectLib.RegisterDefaults
337 db.ResetProfile = DBObjectLib.ResetProfile
340 -- Set some properties in the database object
341 db.profiles = sv.profiles
345 db.defaults = defaults
348 -- store the DB in the registry
349 AceDB.db_registry[db] = true
354 -- handle PLAYER_LOGOUT
355 -- strip all defaults from all databases
356 -- and cleans up empty sections
357 local function logoutHandler(frame, event)
358 if event == "PLAYER_LOGOUT" then
359 for db in pairs(AceDB.db_registry) do
360 db.callbacks:Fire("OnDatabaseShutdown", db)
361 db:RegisterDefaults(nil)
363 -- cleanup sections that are empty without defaults
364 local sv = rawget(db, "sv")
365 for section in pairs(db.keys) do
366 if rawget(sv, section) then
367 -- global is special, all other sections have sub-entrys
368 -- also don't delete empty profiles on main dbs, only on namespaces
369 if section ~= "global" and (section ~= "profiles" or rawget(db, "parent")) then
370 for key in pairs(sv[section]) do
371 if not next(sv[section][key]) then
372 sv[section][key] = nil
376 if not next(sv[section]) then
385 AceDB.frame:RegisterEvent("PLAYER_LOGOUT")
386 AceDB.frame:SetScript("OnEvent", logoutHandler)
389 --[[-------------------------------------------------------------------------
390 AceDB Object Method Definitions
391 ---------------------------------------------------------------------------]]
393 --- Sets the defaults table for the given database object by clearing any
394 -- that are currently set, and then setting the new defaults.
395 -- @param defaults A table of defaults for this database
396 function DBObjectLib:RegisterDefaults(defaults)
397 if defaults and type(defaults) ~= "table" then
398 error("Usage: AceDBObject:RegisterDefaults(defaults): 'defaults' - table or nil expected.", 2)
401 validateDefaults(defaults, self.keys)
403 -- Remove any currently set defaults
404 if self.defaults then
405 for section,key in pairs(self.keys) do
406 if self.defaults[section] and rawget(self, section) then
407 removeDefaults(self[section], self.defaults[section])
412 -- Set the DBObject.defaults table
413 self.defaults = defaults
415 -- Copy in any defaults, only touching those sections already created
417 for section,key in pairs(self.keys) do
418 if defaults[section] and rawget(self, section) then
419 copyDefaults(self[section], defaults[section])
425 --- Changes the profile of the database and all of it's namespaces to the
426 -- supplied named profile
427 -- @param name The name of the profile to set as the current profile
428 function DBObjectLib:SetProfile(name)
429 if type(name) ~= "string" then
430 error("Usage: AceDBObject:SetProfile(name): 'name' - string expected.", 2)
433 -- changing to the same profile, dont do anything
434 if name == self.keys.profile then return end
436 local oldProfile = self.profile
437 local defaults = self.defaults and self.defaults.profile
439 -- Callback: OnProfileShutdown, database
440 self.callbacks:Fire("OnProfileShutdown", self)
442 if oldProfile and defaults then
443 -- Remove the defaults from the old profile
444 removeDefaults(oldProfile, defaults)
448 self.keys["profile"] = name
450 -- if the storage exists, save the new profile
451 -- this won't exist on namespaces.
452 if self.sv.profileKeys then
453 self.sv.profileKeys[charKey] = name
456 -- populate to child namespaces
457 if self.children then
458 for _, db in pairs(self.children) do
459 DBObjectLib.SetProfile(db, name)
463 -- Callback: OnProfileChanged, database, newProfileKey
464 self.callbacks:Fire("OnProfileChanged", self, name)
467 --- Returns a table with the names of the existing profiles in the database.
468 -- You can optionally supply a table to re-use for this purpose.
469 -- @param tbl A table to store the profile names in (optional)
470 function DBObjectLib:GetProfiles(tbl)
471 if tbl and type(tbl) ~= "table" then
472 error("Usage: AceDBObject:GetProfiles(tbl): 'tbl' - table or nil expected.", 2)
475 -- Clear the container table
477 for k,v in pairs(tbl) do tbl[k] = nil end
482 local curProfile = self.keys.profile
485 for profileKey in pairs(self.profiles) do
488 if curProfile and profileKey == curProfile then curProfile = nil end
491 -- Add the current profile, if it hasn't been created yet
500 --- Returns the current profile name used by the database
501 function DBObjectLib:GetCurrentProfile()
502 return self.keys.profile
505 --- Deletes a named profile. This profile must not be the active profile.
506 -- @param name The name of the profile to be deleted
507 -- @param silent If true, do not raise an error when the profile does not exist
508 function DBObjectLib:DeleteProfile(name, silent)
509 if type(name) ~= "string" then
510 error("Usage: AceDBObject:DeleteProfile(name): 'name' - string expected.", 2)
513 if self.keys.profile == name then
514 error("Cannot delete the active profile in an AceDBObject.", 2)
517 if not rawget(self.profiles, name) and not silent then
518 error("Cannot delete profile '" .. name .. "'. It does not exist.", 2)
521 self.profiles[name] = nil
523 -- populate to child namespaces
524 if self.children then
525 for _, db in pairs(self.children) do
526 DBObjectLib.DeleteProfile(db, name, true)
530 -- switch all characters that use this profile back to the default
531 if self.sv.profileKeys then
532 for key, profile in pairs(self.sv.profileKeys) do
533 if profile == name then
534 self.sv.profileKeys[key] = nil
539 -- Callback: OnProfileDeleted, database, profileKey
540 self.callbacks:Fire("OnProfileDeleted", self, name)
543 --- Copies a named profile into the current profile, overwriting any conflicting
545 -- @param name The name of the profile to be copied into the current profile
546 -- @param silent If true, do not raise an error when the profile does not exist
547 function DBObjectLib:CopyProfile(name, silent)
548 if type(name) ~= "string" then
549 error("Usage: AceDBObject:CopyProfile(name): 'name' - string expected.", 2)
552 if name == self.keys.profile then
553 error("Cannot have the same source and destination profiles.", 2)
556 if not rawget(self.profiles, name) and not silent then
557 error("Cannot copy profile '" .. name .. "'. It does not exist.", 2)
560 -- Reset the profile before copying
561 DBObjectLib.ResetProfile(self, nil, true)
563 local profile = self.profile
564 local source = self.profiles[name]
566 copyTable(source, profile)
568 -- populate to child namespaces
569 if self.children then
570 for _, db in pairs(self.children) do
571 DBObjectLib.CopyProfile(db, name, true)
575 -- Callback: OnProfileCopied, database, sourceProfileKey
576 self.callbacks:Fire("OnProfileCopied", self, name)
579 --- Resets the current profile to the default values (if specified).
580 -- @param noChildren if set to true, the reset will not be populated to the child namespaces of this DB object
581 -- @param noCallbacks if set to true, won't fire the OnProfileReset callback
582 function DBObjectLib:ResetProfile(noChildren, noCallbacks)
583 local profile = self.profile
585 for k,v in pairs(profile) do
589 local defaults = self.defaults and self.defaults.profile
591 copyDefaults(profile, defaults)
594 -- populate to child namespaces
595 if self.children and not noChildren then
596 for _, db in pairs(self.children) do
597 DBObjectLib.ResetProfile(db, nil, noCallbacks)
601 -- Callback: OnProfileReset, database
602 if not noCallbacks then
603 self.callbacks:Fire("OnProfileReset", self)
607 --- Resets the entire database, using the string defaultProfile as the new default
609 -- @param defaultProfile The profile name to use as the default
610 function DBObjectLib:ResetDB(defaultProfile)
611 if defaultProfile and type(defaultProfile) ~= "string" then
612 error("Usage: AceDBObject:ResetDB(defaultProfile): 'defaultProfile' - string or nil expected.", 2)
616 for k,v in pairs(sv) do
620 local parent = self.parent
622 initdb(sv, self.defaults, defaultProfile, self)
624 -- fix the child namespaces
625 if self.children then
626 if not sv.namespaces then sv.namespaces = {} end
627 for name, db in pairs(self.children) do
628 if not sv.namespaces[name] then sv.namespaces[name] = {} end
629 initdb(sv.namespaces[name], db.defaults, self.keys.profile, db, self)
633 -- Callback: OnDatabaseReset, database
634 self.callbacks:Fire("OnDatabaseReset", self)
635 -- Callback: OnProfileChanged, database, profileKey
636 self.callbacks:Fire("OnProfileChanged", self, self.keys["profile"])
641 --- Creates a new database namespace, directly tied to the database. This
642 -- is a full scale database in it's own rights other than the fact that
643 -- it cannot control its profile individually
644 -- @param name The name of the new namespace
645 -- @param defaults A table of values to use as defaults
646 function DBObjectLib:RegisterNamespace(name, defaults)
647 if type(name) ~= "string" then
648 error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - string expected.", 2)
650 if defaults and type(defaults) ~= "table" then
651 error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'defaults' - table or nil expected.", 2)
653 if self.children and self.children[name] then
654 error ("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - a namespace with that name already exists.", 2)
658 if not sv.namespaces then sv.namespaces = {} end
659 if not sv.namespaces[name] then
660 sv.namespaces[name] = {}
663 local newDB = initdb(sv.namespaces[name], defaults, self.keys.profile, nil, self)
665 if not self.children then self.children = {} end
666 self.children[name] = newDB
670 --- Returns an already existing namespace from the database object.
671 -- @param name The name of the new namespace
672 -- @param silent if true, the addon is optional, silently return nil if its not found
674 -- local namespace = self.db:GetNamespace('namespace')
675 -- @return the namespace object if found
676 function DBObjectLib:GetNamespace(name, silent)
677 if type(name) ~= "string" then
678 error("Usage: AceDBObject:GetNamespace(name): 'name' - string expected.", 2)
680 if not silent and not (self.children and self.children[name]) then
681 error ("Usage: AceDBObject:GetNamespace(name): 'name' - namespace does not exist.", 2)
683 if not self.children then self.children = {} end
684 return self.children[name]
687 --[[-------------------------------------------------------------------------
688 AceDB Exposed Methods
689 ---------------------------------------------------------------------------]]
691 --- Creates a new database object that can be used to handle database settings and profiles.
692 -- By default, an empty DB is created, using a character specific profile.
694 -- You can override the default profile used by passing any profile name as the third argument,
695 -- or by passing //true// as the third argument to use a globally shared profile called "Default".
697 -- Note that there is no token replacement in the default profile name, passing a defaultProfile as "char"
698 -- will use a profile named "char", and not a character-specific profile.
699 -- @param tbl The name of variable, or table to use for the database
700 -- @param defaults A table of database defaults
701 -- @param defaultProfile The name of the default profile. If not set, a character specific profile will be used as the default.
702 -- You can also pass //true// to use a shared global profile called "Default".
704 -- -- Create an empty DB using a character-specific default profile.
705 -- self.db = LibStub("AceDB-3.0"):New("MyAddonDB")
707 -- -- Create a DB using defaults and using a shared default profile
708 -- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
709 function AceDB:New(tbl, defaults, defaultProfile)
710 if type(tbl) == "string" then
719 if type(tbl) ~= "table" then
720 error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'tbl' - table expected.", 2)
723 if defaults and type(defaults) ~= "table" then
724 error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaults' - table expected.", 2)
727 if defaultProfile and type(defaultProfile) ~= "string" and defaultProfile ~= true then
728 error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaultProfile' - string or true expected.", 2)
731 return initdb(tbl, defaults, defaultProfile)
734 -- upgrade existing databases
735 for db in pairs(AceDB.db_registry) do
736 if not db.parent then
737 for name,func in pairs(DBObjectLib) do
741 db.RegisterDefaults = DBObjectLib.RegisterDefaults
742 db.ResetProfile = DBObjectLib.ResetProfile