| yellowfive@57 | 1 --- **AceDB-3.0** manages the SavedVariables of your addon. | 
| yellowfive@57 | 2 -- It offers profile management, smart defaults and namespaces for modules.\\ | 
| yellowfive@57 | 3 -- Data can be saved in different data-types, depending on its intended usage. | 
| yellowfive@57 | 4 -- The most common data-type is the `profile` type, which allows the user to choose | 
| yellowfive@57 | 5 -- the active profile, and manage the profiles of all of his characters.\\ | 
| yellowfive@57 | 6 -- The following data types are available: | 
| yellowfive@57 | 7 -- * **char** Character-specific data. Every character has its own database. | 
| yellowfive@57 | 8 -- * **realm** Realm-specific data. All of the players characters on the same realm share this database. | 
| yellowfive@57 | 9 -- * **class** Class-specific data. All of the players characters of the same class share this database. | 
| yellowfive@57 | 10 -- * **race** Race-specific data. All of the players characters of the same race share this database. | 
| yellowfive@57 | 11 -- * **faction** Faction-specific data. All of the players characters of the same faction share this database. | 
| yellowfive@57 | 12 -- * **factionrealm** Faction and realm specific data. All of the players characters on the same realm and of the same faction share this database. | 
| yellowfive@106 | 13 -- * **locale** Locale specific data, based on the locale of the players game client. | 
| yellowfive@57 | 14 -- * **global** Global Data. All characters on the same account share this database. | 
| yellowfive@57 | 15 -- * **profile** Profile-specific data. All characters using the same profile share this database. The user can control which profile should be used. | 
| yellowfive@57 | 16 -- | 
| yellowfive@57 | 17 -- Creating a new Database using the `:New` function will return a new DBObject. A database will inherit all functions | 
| yellowfive@57 | 18 -- of the DBObjectLib listed here. \\ | 
| yellowfive@57 | 19 -- If you create a new namespaced child-database (`:RegisterNamespace`), you'll get a DBObject as well, but note | 
| yellowfive@57 | 20 -- that the child-databases cannot individually change their profile, and are linked to their parents profile - and because of that, | 
| yellowfive@57 | 21 -- the profile related APIs are not available. Only `:RegisterDefaults` and `:ResetProfile` are available on child-databases. | 
| yellowfive@57 | 22 -- | 
| yellowfive@57 | 23 -- For more details on how to use AceDB-3.0, see the [[AceDB-3.0 Tutorial]]. | 
| yellowfive@57 | 24 -- | 
| yellowfive@57 | 25 -- You may also be interested in [[libdualspec-1-0|LibDualSpec-1.0]] to do profile switching automatically when switching specs. | 
| yellowfive@57 | 26 -- | 
| yellowfive@57 | 27 -- @usage | 
| yellowfive@57 | 28 -- MyAddon = LibStub("AceAddon-3.0"):NewAddon("DBExample") | 
| yellowfive@57 | 29 -- | 
| yellowfive@57 | 30 -- -- declare defaults to be used in the DB | 
| yellowfive@57 | 31 -- local defaults = { | 
| yellowfive@57 | 32 --   profile = { | 
| yellowfive@57 | 33 --     setting = true, | 
| yellowfive@57 | 34 --   } | 
| yellowfive@57 | 35 -- } | 
| yellowfive@57 | 36 -- | 
| yellowfive@57 | 37 -- function MyAddon:OnInitialize() | 
| yellowfive@57 | 38 --   -- Assuming the .toc says ## SavedVariables: MyAddonDB | 
| yellowfive@57 | 39 --   self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true) | 
| yellowfive@57 | 40 -- end | 
| yellowfive@57 | 41 -- @class file | 
| yellowfive@57 | 42 -- @name AceDB-3.0.lua | 
| yellowfive@106 | 43 -- @release $Id: AceDB-3.0.lua 1142 2016-07-11 08:36:19Z nevcairiel $ | 
| yellowfive@57 | 44 local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 26 | 
| yellowfive@57 | 45 local AceDB, oldminor = LibStub:NewLibrary(ACEDB_MAJOR, ACEDB_MINOR) | 
| yellowfive@57 | 46 | 
| yellowfive@57 | 47 if not AceDB then return end -- No upgrade needed | 
| yellowfive@57 | 48 | 
| yellowfive@57 | 49 -- Lua APIs | 
| yellowfive@57 | 50 local type, pairs, next, error = type, pairs, next, error | 
| yellowfive@57 | 51 local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget | 
| yellowfive@57 | 52 | 
| yellowfive@57 | 53 -- WoW APIs | 
| yellowfive@57 | 54 local _G = _G | 
| yellowfive@57 | 55 | 
| yellowfive@57 | 56 -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded | 
| yellowfive@57 | 57 -- List them here for Mikk's FindGlobals script | 
| yellowfive@57 | 58 -- GLOBALS: LibStub | 
| yellowfive@57 | 59 | 
| yellowfive@57 | 60 AceDB.db_registry = AceDB.db_registry or {} | 
| yellowfive@57 | 61 AceDB.frame = AceDB.frame or CreateFrame("Frame") | 
| yellowfive@57 | 62 | 
| yellowfive@57 | 63 local CallbackHandler | 
| yellowfive@57 | 64 local CallbackDummy = { Fire = function() end } | 
| yellowfive@57 | 65 | 
| yellowfive@57 | 66 local DBObjectLib = {} | 
| yellowfive@57 | 67 | 
| yellowfive@57 | 68 --[[------------------------------------------------------------------------- | 
| yellowfive@57 | 69 	AceDB Utility Functions | 
| yellowfive@57 | 70 ---------------------------------------------------------------------------]] | 
| yellowfive@57 | 71 | 
| yellowfive@57 | 72 -- Simple shallow copy for copying defaults | 
| yellowfive@57 | 73 local function copyTable(src, dest) | 
| yellowfive@57 | 74 	if type(dest) ~= "table" then dest = {} end | 
| yellowfive@57 | 75 	if type(src) == "table" then | 
| yellowfive@57 | 76 		for k,v in pairs(src) do | 
| yellowfive@57 | 77 			if type(v) == "table" then | 
| yellowfive@57 | 78 				-- try to index the key first so that the metatable creates the defaults, if set, and use that table | 
| yellowfive@57 | 79 				v = copyTable(v, dest[k]) | 
| yellowfive@57 | 80 			end | 
| yellowfive@57 | 81 			dest[k] = v | 
| yellowfive@57 | 82 		end | 
| yellowfive@57 | 83 	end | 
| yellowfive@57 | 84 	return dest | 
| yellowfive@57 | 85 end | 
| yellowfive@57 | 86 | 
| yellowfive@57 | 87 -- Called to add defaults to a section of the database | 
| yellowfive@57 | 88 -- | 
| yellowfive@57 | 89 -- When a ["*"] default section is indexed with a new key, a table is returned | 
| yellowfive@57 | 90 -- and set in the host table.  These tables must be cleaned up by removeDefaults | 
| yellowfive@57 | 91 -- in order to ensure we don't write empty default tables. | 
| yellowfive@57 | 92 local function copyDefaults(dest, src) | 
| yellowfive@57 | 93 	-- this happens if some value in the SV overwrites our default value with a non-table | 
| yellowfive@57 | 94 	--if type(dest) ~= "table" then return end | 
| yellowfive@57 | 95 	for k, v in pairs(src) do | 
| yellowfive@57 | 96 		if k == "*" or k == "**" then | 
| yellowfive@57 | 97 			if type(v) == "table" then | 
| yellowfive@57 | 98 				-- This is a metatable used for table defaults | 
| yellowfive@57 | 99 				local mt = { | 
| yellowfive@57 | 100 					-- This handles the lookup and creation of new subtables | 
| yellowfive@57 | 101 					__index = function(t,k) | 
| yellowfive@57 | 102 							if k == nil then return nil end | 
| yellowfive@57 | 103 							local tbl = {} | 
| yellowfive@57 | 104 							copyDefaults(tbl, v) | 
| yellowfive@57 | 105 							rawset(t, k, tbl) | 
| yellowfive@57 | 106 							return tbl | 
| yellowfive@57 | 107 						end, | 
| yellowfive@57 | 108 				} | 
| yellowfive@57 | 109 				setmetatable(dest, mt) | 
| yellowfive@57 | 110 				-- handle already existing tables in the SV | 
| yellowfive@57 | 111 				for dk, dv in pairs(dest) do | 
| yellowfive@57 | 112 					if not rawget(src, dk) and type(dv) == "table" then | 
| yellowfive@57 | 113 						copyDefaults(dv, v) | 
| yellowfive@57 | 114 					end | 
| yellowfive@57 | 115 				end | 
| yellowfive@57 | 116 			else | 
| yellowfive@57 | 117 				-- Values are not tables, so this is just a simple return | 
| yellowfive@57 | 118 				local mt = {__index = function(t,k) return k~=nil and v or nil end} | 
| yellowfive@57 | 119 				setmetatable(dest, mt) | 
| yellowfive@57 | 120 			end | 
| yellowfive@57 | 121 		elseif type(v) == "table" then | 
| yellowfive@57 | 122 			if not rawget(dest, k) then rawset(dest, k, {}) end | 
| yellowfive@57 | 123 			if type(dest[k]) == "table" then | 
| yellowfive@57 | 124 				copyDefaults(dest[k], v) | 
| yellowfive@57 | 125 				if src['**'] then | 
| yellowfive@57 | 126 					copyDefaults(dest[k], src['**']) | 
| yellowfive@57 | 127 				end | 
| yellowfive@57 | 128 			end | 
| yellowfive@57 | 129 		else | 
| yellowfive@57 | 130 			if rawget(dest, k) == nil then | 
| yellowfive@57 | 131 				rawset(dest, k, v) | 
| yellowfive@57 | 132 			end | 
| yellowfive@57 | 133 		end | 
| yellowfive@57 | 134 	end | 
| yellowfive@57 | 135 end | 
| yellowfive@57 | 136 | 
| yellowfive@57 | 137 -- Called to remove all defaults in the default table from the database | 
| yellowfive@57 | 138 local function removeDefaults(db, defaults, blocker) | 
| yellowfive@57 | 139 	-- remove all metatables from the db, so we don't accidentally create new sub-tables through them | 
| yellowfive@57 | 140 	setmetatable(db, nil) | 
| yellowfive@57 | 141 	-- loop through the defaults and remove their content | 
| yellowfive@57 | 142 	for k,v in pairs(defaults) do | 
| yellowfive@57 | 143 		if k == "*" or k == "**" then | 
| yellowfive@57 | 144 			if type(v) == "table" then | 
| yellowfive@57 | 145 				-- Loop through all the actual k,v pairs and remove | 
| yellowfive@57 | 146 				for key, value in pairs(db) do | 
| yellowfive@57 | 147 					if type(value) == "table" then | 
| yellowfive@57 | 148 						-- if the key was not explicitly specified in the defaults table, just strip everything from * and ** tables | 
| yellowfive@57 | 149 						if defaults[key] == nil and (not blocker or blocker[key] == nil) then | 
| yellowfive@57 | 150 							removeDefaults(value, v) | 
| yellowfive@57 | 151 							-- if the table is empty afterwards, remove it | 
| yellowfive@57 | 152 							if next(value) == nil then | 
| yellowfive@57 | 153 								db[key] = nil | 
| yellowfive@57 | 154 							end | 
| yellowfive@57 | 155 						-- if it was specified, only strip ** content, but block values which were set in the key table | 
| yellowfive@57 | 156 						elseif k == "**" then | 
| yellowfive@57 | 157 							removeDefaults(value, v, defaults[key]) | 
| yellowfive@57 | 158 						end | 
| yellowfive@57 | 159 					end | 
| yellowfive@57 | 160 				end | 
| yellowfive@57 | 161 			elseif k == "*" then | 
| yellowfive@57 | 162 				-- check for non-table default | 
| yellowfive@57 | 163 				for key, value in pairs(db) do | 
| yellowfive@57 | 164 					if defaults[key] == nil and v == value then | 
| yellowfive@57 | 165 						db[key] = nil | 
| yellowfive@57 | 166 					end | 
| yellowfive@57 | 167 				end | 
| yellowfive@57 | 168 			end | 
| yellowfive@57 | 169 		elseif type(v) == "table" and type(db[k]) == "table" then | 
| yellowfive@57 | 170 			-- if a blocker was set, dive into it, to allow multi-level defaults | 
| yellowfive@57 | 171 			removeDefaults(db[k], v, blocker and blocker[k]) | 
| yellowfive@57 | 172 			if next(db[k]) == nil then | 
| yellowfive@57 | 173 				db[k] = nil | 
| yellowfive@57 | 174 			end | 
| yellowfive@57 | 175 		else | 
| yellowfive@57 | 176 			-- check if the current value matches the default, and that its not blocked by another defaults table | 
| yellowfive@57 | 177 			if db[k] == defaults[k] and (not blocker or blocker[k] == nil) then | 
| yellowfive@57 | 178 				db[k] = nil | 
| yellowfive@57 | 179 			end | 
| yellowfive@57 | 180 		end | 
| yellowfive@57 | 181 	end | 
| yellowfive@57 | 182 end | 
| yellowfive@57 | 183 | 
| yellowfive@57 | 184 -- This is called when a table section is first accessed, to set up the defaults | 
| yellowfive@57 | 185 local function initSection(db, section, svstore, key, defaults) | 
| yellowfive@57 | 186 	local sv = rawget(db, "sv") | 
| yellowfive@57 | 187 | 
| yellowfive@57 | 188 	local tableCreated | 
| yellowfive@57 | 189 	if not sv[svstore] then sv[svstore] = {} end | 
| yellowfive@57 | 190 	if not sv[svstore][key] then | 
| yellowfive@57 | 191 		sv[svstore][key] = {} | 
| yellowfive@57 | 192 		tableCreated = true | 
| yellowfive@57 | 193 	end | 
| yellowfive@57 | 194 | 
| yellowfive@57 | 195 	local tbl = sv[svstore][key] | 
| yellowfive@57 | 196 | 
| yellowfive@57 | 197 	if defaults then | 
| yellowfive@57 | 198 		copyDefaults(tbl, defaults) | 
| yellowfive@57 | 199 	end | 
| yellowfive@57 | 200 	rawset(db, section, tbl) | 
| yellowfive@57 | 201 | 
| yellowfive@57 | 202 	return tableCreated, tbl | 
| yellowfive@57 | 203 end | 
| yellowfive@57 | 204 | 
| yellowfive@57 | 205 -- Metatable to handle the dynamic creation of sections and copying of sections. | 
| yellowfive@57 | 206 local dbmt = { | 
| yellowfive@57 | 207 	__index = function(t, section) | 
| yellowfive@57 | 208 			local keys = rawget(t, "keys") | 
| yellowfive@57 | 209 			local key = keys[section] | 
| yellowfive@57 | 210 			if key then | 
| yellowfive@57 | 211 				local defaultTbl = rawget(t, "defaults") | 
| yellowfive@57 | 212 				local defaults = defaultTbl and defaultTbl[section] | 
| yellowfive@57 | 213 | 
| yellowfive@57 | 214 				if section == "profile" then | 
| yellowfive@57 | 215 					local new = initSection(t, section, "profiles", key, defaults) | 
| yellowfive@57 | 216 					if new then | 
| yellowfive@57 | 217 						-- Callback: OnNewProfile, database, newProfileKey | 
| yellowfive@57 | 218 						t.callbacks:Fire("OnNewProfile", t, key) | 
| yellowfive@57 | 219 					end | 
| yellowfive@57 | 220 				elseif section == "profiles" then | 
| yellowfive@57 | 221 					local sv = rawget(t, "sv") | 
| yellowfive@57 | 222 					if not sv.profiles then sv.profiles = {} end | 
| yellowfive@57 | 223 					rawset(t, "profiles", sv.profiles) | 
| yellowfive@57 | 224 				elseif section == "global" then | 
| yellowfive@57 | 225 					local sv = rawget(t, "sv") | 
| yellowfive@57 | 226 					if not sv.global then sv.global = {} end | 
| yellowfive@57 | 227 					if defaults then | 
| yellowfive@57 | 228 						copyDefaults(sv.global, defaults) | 
| yellowfive@57 | 229 					end | 
| yellowfive@57 | 230 					rawset(t, section, sv.global) | 
| yellowfive@57 | 231 				else | 
| yellowfive@57 | 232 					initSection(t, section, section, key, defaults) | 
| yellowfive@57 | 233 				end | 
| yellowfive@57 | 234 			end | 
| yellowfive@57 | 235 | 
| yellowfive@57 | 236 			return rawget(t, section) | 
| yellowfive@57 | 237 		end | 
| yellowfive@57 | 238 } | 
| yellowfive@57 | 239 | 
| yellowfive@57 | 240 local function validateDefaults(defaults, keyTbl, offset) | 
| yellowfive@57 | 241 	if not defaults then return end | 
| yellowfive@57 | 242 	offset = offset or 0 | 
| yellowfive@57 | 243 	for k in pairs(defaults) do | 
| yellowfive@57 | 244 		if not keyTbl[k] or k == "profiles" then | 
| yellowfive@57 | 245 			error(("Usage: AceDBObject:RegisterDefaults(defaults): '%s' is not a valid datatype."):format(k), 3 + offset) | 
| yellowfive@57 | 246 		end | 
| yellowfive@57 | 247 	end | 
| yellowfive@57 | 248 end | 
| yellowfive@57 | 249 | 
| yellowfive@57 | 250 local preserve_keys = { | 
| yellowfive@57 | 251 	["callbacks"] = true, | 
| yellowfive@57 | 252 	["RegisterCallback"] = true, | 
| yellowfive@57 | 253 	["UnregisterCallback"] = true, | 
| yellowfive@57 | 254 	["UnregisterAllCallbacks"] = true, | 
| yellowfive@57 | 255 	["children"] = true, | 
| yellowfive@57 | 256 } | 
| yellowfive@57 | 257 | 
| yellowfive@57 | 258 local realmKey = GetRealmName() | 
| yellowfive@57 | 259 local charKey = UnitName("player") .. " - " .. realmKey | 
| yellowfive@57 | 260 local _, classKey = UnitClass("player") | 
| yellowfive@57 | 261 local _, raceKey = UnitRace("player") | 
| yellowfive@57 | 262 local factionKey = UnitFactionGroup("player") | 
| yellowfive@57 | 263 local factionrealmKey = factionKey .. " - " .. realmKey | 
| yellowfive@57 | 264 local localeKey = GetLocale():lower() | 
| yellowfive@57 | 265 | 
| yellowfive@57 | 266 local regionTable = { "US", "KR", "EU", "TW", "CN" } | 
| yellowfive@57 | 267 local regionKey = regionTable[GetCurrentRegion()] | 
| yellowfive@57 | 268 local factionrealmregionKey = factionrealmKey .. " - " .. regionKey | 
| yellowfive@57 | 269 | 
| yellowfive@57 | 270 -- Actual database initialization function | 
| yellowfive@57 | 271 local function initdb(sv, defaults, defaultProfile, olddb, parent) | 
| yellowfive@57 | 272 	-- Generate the database keys for each section | 
| yellowfive@57 | 273 | 
| yellowfive@57 | 274 	-- map "true" to our "Default" profile | 
| yellowfive@57 | 275 	if defaultProfile == true then defaultProfile = "Default" end | 
| yellowfive@57 | 276 | 
| yellowfive@57 | 277 	local profileKey | 
| yellowfive@57 | 278 	if not parent then | 
| yellowfive@57 | 279 		-- Make a container for profile keys | 
| yellowfive@57 | 280 		if not sv.profileKeys then sv.profileKeys = {} end | 
| yellowfive@57 | 281 | 
| yellowfive@57 | 282 		-- Try to get the profile selected from the char db | 
| yellowfive@57 | 283 		profileKey = sv.profileKeys[charKey] or defaultProfile or charKey | 
| yellowfive@57 | 284 | 
| yellowfive@57 | 285 		-- save the selected profile for later | 
| yellowfive@57 | 286 		sv.profileKeys[charKey] = profileKey | 
| yellowfive@57 | 287 	else | 
| yellowfive@57 | 288 		-- Use the profile of the parents DB | 
| yellowfive@57 | 289 		profileKey = parent.keys.profile or defaultProfile or charKey | 
| yellowfive@57 | 290 | 
| yellowfive@57 | 291 		-- clear the profileKeys in the DB, namespaces don't need to store them | 
| yellowfive@57 | 292 		sv.profileKeys = nil | 
| yellowfive@57 | 293 	end | 
| yellowfive@57 | 294 | 
| yellowfive@57 | 295 	-- This table contains keys that enable the dynamic creation | 
| yellowfive@57 | 296 	-- of each section of the table.  The 'global' and 'profiles' | 
| yellowfive@57 | 297 	-- have a key of true, since they are handled in a special case | 
| yellowfive@57 | 298 	local keyTbl= { | 
| yellowfive@57 | 299 		["char"] = charKey, | 
| yellowfive@57 | 300 		["realm"] = realmKey, | 
| yellowfive@57 | 301 		["class"] = classKey, | 
| yellowfive@57 | 302 		["race"] = raceKey, | 
| yellowfive@57 | 303 		["faction"] = factionKey, | 
| yellowfive@57 | 304 		["factionrealm"] = factionrealmKey, | 
| yellowfive@57 | 305 		["factionrealmregion"] = factionrealmregionKey, | 
| yellowfive@57 | 306 		["profile"] = profileKey, | 
| yellowfive@57 | 307 		["locale"] = localeKey, | 
| yellowfive@57 | 308 		["global"] = true, | 
| yellowfive@57 | 309 		["profiles"] = true, | 
| yellowfive@57 | 310 	} | 
| yellowfive@57 | 311 | 
| yellowfive@57 | 312 	validateDefaults(defaults, keyTbl, 1) | 
| yellowfive@57 | 313 | 
| yellowfive@57 | 314 	-- This allows us to use this function to reset an entire database | 
| yellowfive@57 | 315 	-- Clear out the old database | 
| yellowfive@57 | 316 	if olddb then | 
| yellowfive@57 | 317 		for k,v in pairs(olddb) do if not preserve_keys[k] then olddb[k] = nil end end | 
| yellowfive@57 | 318 	end | 
| yellowfive@57 | 319 | 
| yellowfive@57 | 320 	-- Give this database the metatable so it initializes dynamically | 
| yellowfive@57 | 321 	local db = setmetatable(olddb or {}, dbmt) | 
| yellowfive@57 | 322 | 
| yellowfive@57 | 323 	if not rawget(db, "callbacks") then | 
| yellowfive@57 | 324 		-- try to load CallbackHandler-1.0 if it loaded after our library | 
| yellowfive@57 | 325 		if not CallbackHandler then CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0", true) end | 
| yellowfive@57 | 326 		db.callbacks = CallbackHandler and CallbackHandler:New(db) or CallbackDummy | 
| yellowfive@57 | 327 	end | 
| yellowfive@57 | 328 | 
| yellowfive@57 | 329 	-- Copy methods locally into the database object, to avoid hitting | 
| yellowfive@57 | 330 	-- the metatable when calling methods | 
| yellowfive@57 | 331 | 
| yellowfive@57 | 332 	if not parent then | 
| yellowfive@57 | 333 		for name, func in pairs(DBObjectLib) do | 
| yellowfive@57 | 334 			db[name] = func | 
| yellowfive@57 | 335 		end | 
| yellowfive@57 | 336 	else | 
| yellowfive@57 | 337 		-- hack this one in | 
| yellowfive@57 | 338 		db.RegisterDefaults = DBObjectLib.RegisterDefaults | 
| yellowfive@57 | 339 		db.ResetProfile = DBObjectLib.ResetProfile | 
| yellowfive@57 | 340 	end | 
| yellowfive@57 | 341 | 
| yellowfive@57 | 342 	-- Set some properties in the database object | 
| yellowfive@57 | 343 	db.profiles = sv.profiles | 
| yellowfive@57 | 344 	db.keys = keyTbl | 
| yellowfive@57 | 345 	db.sv = sv | 
| yellowfive@57 | 346 	--db.sv_name = name | 
| yellowfive@57 | 347 	db.defaults = defaults | 
| yellowfive@57 | 348 	db.parent = parent | 
| yellowfive@57 | 349 | 
| yellowfive@57 | 350 	-- store the DB in the registry | 
| yellowfive@57 | 351 	AceDB.db_registry[db] = true | 
| yellowfive@57 | 352 | 
| yellowfive@57 | 353 	return db | 
| yellowfive@57 | 354 end | 
| yellowfive@57 | 355 | 
| yellowfive@57 | 356 -- handle PLAYER_LOGOUT | 
| yellowfive@57 | 357 -- strip all defaults from all databases | 
| yellowfive@57 | 358 -- and cleans up empty sections | 
| yellowfive@57 | 359 local function logoutHandler(frame, event) | 
| yellowfive@57 | 360 	if event == "PLAYER_LOGOUT" then | 
| yellowfive@57 | 361 		for db in pairs(AceDB.db_registry) do | 
| yellowfive@57 | 362 			db.callbacks:Fire("OnDatabaseShutdown", db) | 
| yellowfive@57 | 363 			db:RegisterDefaults(nil) | 
| yellowfive@57 | 364 | 
| yellowfive@57 | 365 			-- cleanup sections that are empty without defaults | 
| yellowfive@57 | 366 			local sv = rawget(db, "sv") | 
| yellowfive@57 | 367 			for section in pairs(db.keys) do | 
| yellowfive@57 | 368 				if rawget(sv, section) then | 
| yellowfive@57 | 369 					-- global is special, all other sections have sub-entrys | 
| yellowfive@57 | 370 					-- also don't delete empty profiles on main dbs, only on namespaces | 
| yellowfive@57 | 371 					if section ~= "global" and (section ~= "profiles" or rawget(db, "parent")) then | 
| yellowfive@57 | 372 						for key in pairs(sv[section]) do | 
| yellowfive@57 | 373 							if not next(sv[section][key]) then | 
| yellowfive@57 | 374 								sv[section][key] = nil | 
| yellowfive@57 | 375 							end | 
| yellowfive@57 | 376 						end | 
| yellowfive@57 | 377 					end | 
| yellowfive@57 | 378 					if not next(sv[section]) then | 
| yellowfive@57 | 379 						sv[section] = nil | 
| yellowfive@57 | 380 					end | 
| yellowfive@57 | 381 				end | 
| yellowfive@57 | 382 			end | 
| yellowfive@57 | 383 		end | 
| yellowfive@57 | 384 	end | 
| yellowfive@57 | 385 end | 
| yellowfive@57 | 386 | 
| yellowfive@57 | 387 AceDB.frame:RegisterEvent("PLAYER_LOGOUT") | 
| yellowfive@57 | 388 AceDB.frame:SetScript("OnEvent", logoutHandler) | 
| yellowfive@57 | 389 | 
| yellowfive@57 | 390 | 
| yellowfive@57 | 391 --[[------------------------------------------------------------------------- | 
| yellowfive@57 | 392 	AceDB Object Method Definitions | 
| yellowfive@57 | 393 ---------------------------------------------------------------------------]] | 
| yellowfive@57 | 394 | 
| yellowfive@57 | 395 --- Sets the defaults table for the given database object by clearing any | 
| yellowfive@57 | 396 -- that are currently set, and then setting the new defaults. | 
| yellowfive@57 | 397 -- @param defaults A table of defaults for this database | 
| yellowfive@57 | 398 function DBObjectLib:RegisterDefaults(defaults) | 
| yellowfive@57 | 399 	if defaults and type(defaults) ~= "table" then | 
| yellowfive@57 | 400 		error("Usage: AceDBObject:RegisterDefaults(defaults): 'defaults' - table or nil expected.", 2) | 
| yellowfive@57 | 401 	end | 
| yellowfive@57 | 402 | 
| yellowfive@57 | 403 	validateDefaults(defaults, self.keys) | 
| yellowfive@57 | 404 | 
| yellowfive@57 | 405 	-- Remove any currently set defaults | 
| yellowfive@57 | 406 	if self.defaults then | 
| yellowfive@57 | 407 		for section,key in pairs(self.keys) do | 
| yellowfive@57 | 408 			if self.defaults[section] and rawget(self, section) then | 
| yellowfive@57 | 409 				removeDefaults(self[section], self.defaults[section]) | 
| yellowfive@57 | 410 			end | 
| yellowfive@57 | 411 		end | 
| yellowfive@57 | 412 	end | 
| yellowfive@57 | 413 | 
| yellowfive@57 | 414 	-- Set the DBObject.defaults table | 
| yellowfive@57 | 415 	self.defaults = defaults | 
| yellowfive@57 | 416 | 
| yellowfive@57 | 417 	-- Copy in any defaults, only touching those sections already created | 
| yellowfive@57 | 418 	if defaults then | 
| yellowfive@57 | 419 		for section,key in pairs(self.keys) do | 
| yellowfive@57 | 420 			if defaults[section] and rawget(self, section) then | 
| yellowfive@57 | 421 				copyDefaults(self[section], defaults[section]) | 
| yellowfive@57 | 422 			end | 
| yellowfive@57 | 423 		end | 
| yellowfive@57 | 424 	end | 
| yellowfive@57 | 425 end | 
| yellowfive@57 | 426 | 
| yellowfive@57 | 427 --- Changes the profile of the database and all of it's namespaces to the | 
| yellowfive@57 | 428 -- supplied named profile | 
| yellowfive@57 | 429 -- @param name The name of the profile to set as the current profile | 
| yellowfive@57 | 430 function DBObjectLib:SetProfile(name) | 
| yellowfive@57 | 431 	if type(name) ~= "string" then | 
| yellowfive@57 | 432 		error("Usage: AceDBObject:SetProfile(name): 'name' - string expected.", 2) | 
| yellowfive@57 | 433 	end | 
| yellowfive@57 | 434 | 
| yellowfive@57 | 435 	-- changing to the same profile, dont do anything | 
| yellowfive@57 | 436 	if name == self.keys.profile then return end | 
| yellowfive@57 | 437 | 
| yellowfive@57 | 438 	local oldProfile = self.profile | 
| yellowfive@57 | 439 	local defaults = self.defaults and self.defaults.profile | 
| yellowfive@57 | 440 | 
| yellowfive@57 | 441 	-- Callback: OnProfileShutdown, database | 
| yellowfive@57 | 442 	self.callbacks:Fire("OnProfileShutdown", self) | 
| yellowfive@57 | 443 | 
| yellowfive@57 | 444 	if oldProfile and defaults then | 
| yellowfive@57 | 445 		-- Remove the defaults from the old profile | 
| yellowfive@57 | 446 		removeDefaults(oldProfile, defaults) | 
| yellowfive@57 | 447 	end | 
| yellowfive@57 | 448 | 
| yellowfive@57 | 449 	self.profile = nil | 
| yellowfive@57 | 450 	self.keys["profile"] = name | 
| yellowfive@57 | 451 | 
| yellowfive@57 | 452 	-- if the storage exists, save the new profile | 
| yellowfive@57 | 453 	-- this won't exist on namespaces. | 
| yellowfive@57 | 454 	if self.sv.profileKeys then | 
| yellowfive@57 | 455 		self.sv.profileKeys[charKey] = name | 
| yellowfive@57 | 456 	end | 
| yellowfive@57 | 457 | 
| yellowfive@57 | 458 	-- populate to child namespaces | 
| yellowfive@57 | 459 	if self.children then | 
| yellowfive@57 | 460 		for _, db in pairs(self.children) do | 
| yellowfive@57 | 461 			DBObjectLib.SetProfile(db, name) | 
| yellowfive@57 | 462 		end | 
| yellowfive@57 | 463 	end | 
| yellowfive@57 | 464 | 
| yellowfive@57 | 465 	-- Callback: OnProfileChanged, database, newProfileKey | 
| yellowfive@57 | 466 	self.callbacks:Fire("OnProfileChanged", self, name) | 
| yellowfive@57 | 467 end | 
| yellowfive@57 | 468 | 
| yellowfive@57 | 469 --- Returns a table with the names of the existing profiles in the database. | 
| yellowfive@57 | 470 -- You can optionally supply a table to re-use for this purpose. | 
| yellowfive@57 | 471 -- @param tbl A table to store the profile names in (optional) | 
| yellowfive@57 | 472 function DBObjectLib:GetProfiles(tbl) | 
| yellowfive@57 | 473 	if tbl and type(tbl) ~= "table" then | 
| yellowfive@57 | 474 		error("Usage: AceDBObject:GetProfiles(tbl): 'tbl' - table or nil expected.", 2) | 
| yellowfive@57 | 475 	end | 
| yellowfive@57 | 476 | 
| yellowfive@57 | 477 	-- Clear the container table | 
| yellowfive@57 | 478 	if tbl then | 
| yellowfive@57 | 479 		for k,v in pairs(tbl) do tbl[k] = nil end | 
| yellowfive@57 | 480 	else | 
| yellowfive@57 | 481 		tbl = {} | 
| yellowfive@57 | 482 	end | 
| yellowfive@57 | 483 | 
| yellowfive@57 | 484 	local curProfile = self.keys.profile | 
| yellowfive@57 | 485 | 
| yellowfive@57 | 486 	local i = 0 | 
| yellowfive@57 | 487 	for profileKey in pairs(self.profiles) do | 
| yellowfive@57 | 488 		i = i + 1 | 
| yellowfive@57 | 489 		tbl[i] = profileKey | 
| yellowfive@57 | 490 		if curProfile and profileKey == curProfile then curProfile = nil end | 
| yellowfive@57 | 491 	end | 
| yellowfive@57 | 492 | 
| yellowfive@57 | 493 	-- Add the current profile, if it hasn't been created yet | 
| yellowfive@57 | 494 	if curProfile then | 
| yellowfive@57 | 495 		i = i + 1 | 
| yellowfive@57 | 496 		tbl[i] = curProfile | 
| yellowfive@57 | 497 	end | 
| yellowfive@57 | 498 | 
| yellowfive@57 | 499 	return tbl, i | 
| yellowfive@57 | 500 end | 
| yellowfive@57 | 501 | 
| yellowfive@57 | 502 --- Returns the current profile name used by the database | 
| yellowfive@57 | 503 function DBObjectLib:GetCurrentProfile() | 
| yellowfive@57 | 504 	return self.keys.profile | 
| yellowfive@57 | 505 end | 
| yellowfive@57 | 506 | 
| yellowfive@57 | 507 --- Deletes a named profile.  This profile must not be the active profile. | 
| yellowfive@57 | 508 -- @param name The name of the profile to be deleted | 
| yellowfive@57 | 509 -- @param silent If true, do not raise an error when the profile does not exist | 
| yellowfive@57 | 510 function DBObjectLib:DeleteProfile(name, silent) | 
| yellowfive@57 | 511 	if type(name) ~= "string" then | 
| yellowfive@57 | 512 		error("Usage: AceDBObject:DeleteProfile(name): 'name' - string expected.", 2) | 
| yellowfive@57 | 513 	end | 
| yellowfive@57 | 514 | 
| yellowfive@57 | 515 	if self.keys.profile == name then | 
| yellowfive@57 | 516 		error("Cannot delete the active profile in an AceDBObject.", 2) | 
| yellowfive@57 | 517 	end | 
| yellowfive@57 | 518 | 
| yellowfive@57 | 519 	if not rawget(self.profiles, name) and not silent then | 
| yellowfive@57 | 520 		error("Cannot delete profile '" .. name .. "'. It does not exist.", 2) | 
| yellowfive@57 | 521 	end | 
| yellowfive@57 | 522 | 
| yellowfive@57 | 523 	self.profiles[name] = nil | 
| yellowfive@57 | 524 | 
| yellowfive@57 | 525 	-- populate to child namespaces | 
| yellowfive@57 | 526 	if self.children then | 
| yellowfive@57 | 527 		for _, db in pairs(self.children) do | 
| yellowfive@57 | 528 			DBObjectLib.DeleteProfile(db, name, true) | 
| yellowfive@57 | 529 		end | 
| yellowfive@57 | 530 	end | 
| yellowfive@57 | 531 | 
| yellowfive@57 | 532 	-- switch all characters that use this profile back to the default | 
| yellowfive@57 | 533 	if self.sv.profileKeys then | 
| yellowfive@57 | 534 		for key, profile in pairs(self.sv.profileKeys) do | 
| yellowfive@57 | 535 			if profile == name then | 
| yellowfive@57 | 536 				self.sv.profileKeys[key] = nil | 
| yellowfive@57 | 537 			end | 
| yellowfive@57 | 538 		end | 
| yellowfive@57 | 539 	end | 
| yellowfive@57 | 540 | 
| yellowfive@57 | 541 	-- Callback: OnProfileDeleted, database, profileKey | 
| yellowfive@57 | 542 	self.callbacks:Fire("OnProfileDeleted", self, name) | 
| yellowfive@57 | 543 end | 
| yellowfive@57 | 544 | 
| yellowfive@57 | 545 --- Copies a named profile into the current profile, overwriting any conflicting | 
| yellowfive@57 | 546 -- settings. | 
| yellowfive@57 | 547 -- @param name The name of the profile to be copied into the current profile | 
| yellowfive@57 | 548 -- @param silent If true, do not raise an error when the profile does not exist | 
| yellowfive@57 | 549 function DBObjectLib:CopyProfile(name, silent) | 
| yellowfive@57 | 550 	if type(name) ~= "string" then | 
| yellowfive@57 | 551 		error("Usage: AceDBObject:CopyProfile(name): 'name' - string expected.", 2) | 
| yellowfive@57 | 552 	end | 
| yellowfive@57 | 553 | 
| yellowfive@57 | 554 	if name == self.keys.profile then | 
| yellowfive@57 | 555 		error("Cannot have the same source and destination profiles.", 2) | 
| yellowfive@57 | 556 	end | 
| yellowfive@57 | 557 | 
| yellowfive@57 | 558 	if not rawget(self.profiles, name) and not silent then | 
| yellowfive@57 | 559 		error("Cannot copy profile '" .. name .. "'. It does not exist.", 2) | 
| yellowfive@57 | 560 	end | 
| yellowfive@57 | 561 | 
| yellowfive@57 | 562 	-- Reset the profile before copying | 
| yellowfive@57 | 563 	DBObjectLib.ResetProfile(self, nil, true) | 
| yellowfive@57 | 564 | 
| yellowfive@57 | 565 	local profile = self.profile | 
| yellowfive@57 | 566 	local source = self.profiles[name] | 
| yellowfive@57 | 567 | 
| yellowfive@57 | 568 	copyTable(source, profile) | 
| yellowfive@57 | 569 | 
| yellowfive@57 | 570 	-- populate to child namespaces | 
| yellowfive@57 | 571 	if self.children then | 
| yellowfive@57 | 572 		for _, db in pairs(self.children) do | 
| yellowfive@57 | 573 			DBObjectLib.CopyProfile(db, name, true) | 
| yellowfive@57 | 574 		end | 
| yellowfive@57 | 575 	end | 
| yellowfive@57 | 576 | 
| yellowfive@57 | 577 	-- Callback: OnProfileCopied, database, sourceProfileKey | 
| yellowfive@57 | 578 	self.callbacks:Fire("OnProfileCopied", self, name) | 
| yellowfive@57 | 579 end | 
| yellowfive@57 | 580 | 
| yellowfive@57 | 581 --- Resets the current profile to the default values (if specified). | 
| yellowfive@57 | 582 -- @param noChildren if set to true, the reset will not be populated to the child namespaces of this DB object | 
| yellowfive@57 | 583 -- @param noCallbacks if set to true, won't fire the OnProfileReset callback | 
| yellowfive@57 | 584 function DBObjectLib:ResetProfile(noChildren, noCallbacks) | 
| yellowfive@57 | 585 	local profile = self.profile | 
| yellowfive@57 | 586 | 
| yellowfive@57 | 587 	for k,v in pairs(profile) do | 
| yellowfive@57 | 588 		profile[k] = nil | 
| yellowfive@57 | 589 	end | 
| yellowfive@57 | 590 | 
| yellowfive@57 | 591 	local defaults = self.defaults and self.defaults.profile | 
| yellowfive@57 | 592 	if defaults then | 
| yellowfive@57 | 593 		copyDefaults(profile, defaults) | 
| yellowfive@57 | 594 	end | 
| yellowfive@57 | 595 | 
| yellowfive@57 | 596 	-- populate to child namespaces | 
| yellowfive@57 | 597 	if self.children and not noChildren then | 
| yellowfive@57 | 598 		for _, db in pairs(self.children) do | 
| yellowfive@57 | 599 			DBObjectLib.ResetProfile(db, nil, noCallbacks) | 
| yellowfive@57 | 600 		end | 
| yellowfive@57 | 601 	end | 
| yellowfive@57 | 602 | 
| yellowfive@57 | 603 	-- Callback: OnProfileReset, database | 
| yellowfive@57 | 604 	if not noCallbacks then | 
| yellowfive@57 | 605 		self.callbacks:Fire("OnProfileReset", self) | 
| yellowfive@57 | 606 	end | 
| yellowfive@57 | 607 end | 
| yellowfive@57 | 608 | 
| yellowfive@57 | 609 --- Resets the entire database, using the string defaultProfile as the new default | 
| yellowfive@57 | 610 -- profile. | 
| yellowfive@57 | 611 -- @param defaultProfile The profile name to use as the default | 
| yellowfive@57 | 612 function DBObjectLib:ResetDB(defaultProfile) | 
| yellowfive@57 | 613 	if defaultProfile and type(defaultProfile) ~= "string" then | 
| yellowfive@57 | 614 		error("Usage: AceDBObject:ResetDB(defaultProfile): 'defaultProfile' - string or nil expected.", 2) | 
| yellowfive@57 | 615 	end | 
| yellowfive@57 | 616 | 
| yellowfive@57 | 617 	local sv = self.sv | 
| yellowfive@57 | 618 	for k,v in pairs(sv) do | 
| yellowfive@57 | 619 		sv[k] = nil | 
| yellowfive@57 | 620 	end | 
| yellowfive@57 | 621 | 
| yellowfive@57 | 622 	local parent = self.parent | 
| yellowfive@57 | 623 | 
| yellowfive@57 | 624 	initdb(sv, self.defaults, defaultProfile, self) | 
| yellowfive@57 | 625 | 
| yellowfive@57 | 626 	-- fix the child namespaces | 
| yellowfive@57 | 627 	if self.children then | 
| yellowfive@57 | 628 		if not sv.namespaces then sv.namespaces = {} end | 
| yellowfive@57 | 629 		for name, db in pairs(self.children) do | 
| yellowfive@57 | 630 			if not sv.namespaces[name] then sv.namespaces[name] = {} end | 
| yellowfive@57 | 631 			initdb(sv.namespaces[name], db.defaults, self.keys.profile, db, self) | 
| yellowfive@57 | 632 		end | 
| yellowfive@57 | 633 	end | 
| yellowfive@57 | 634 | 
| yellowfive@57 | 635 	-- Callback: OnDatabaseReset, database | 
| yellowfive@57 | 636 	self.callbacks:Fire("OnDatabaseReset", self) | 
| yellowfive@57 | 637 	-- Callback: OnProfileChanged, database, profileKey | 
| yellowfive@57 | 638 	self.callbacks:Fire("OnProfileChanged", self, self.keys["profile"]) | 
| yellowfive@57 | 639 | 
| yellowfive@57 | 640 	return self | 
| yellowfive@57 | 641 end | 
| yellowfive@57 | 642 | 
| yellowfive@57 | 643 --- Creates a new database namespace, directly tied to the database.  This | 
| yellowfive@57 | 644 -- is a full scale database in it's own rights other than the fact that | 
| yellowfive@57 | 645 -- it cannot control its profile individually | 
| yellowfive@57 | 646 -- @param name The name of the new namespace | 
| yellowfive@57 | 647 -- @param defaults A table of values to use as defaults | 
| yellowfive@57 | 648 function DBObjectLib:RegisterNamespace(name, defaults) | 
| yellowfive@57 | 649 	if type(name) ~= "string" then | 
| yellowfive@57 | 650 		error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - string expected.", 2) | 
| yellowfive@57 | 651 	end | 
| yellowfive@57 | 652 	if defaults and type(defaults) ~= "table" then | 
| yellowfive@57 | 653 		error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'defaults' - table or nil expected.", 2) | 
| yellowfive@57 | 654 	end | 
| yellowfive@57 | 655 	if self.children and self.children[name] then | 
| yellowfive@57 | 656 		error ("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - a namespace with that name already exists.", 2) | 
| yellowfive@57 | 657 	end | 
| yellowfive@57 | 658 | 
| yellowfive@57 | 659 	local sv = self.sv | 
| yellowfive@57 | 660 	if not sv.namespaces then sv.namespaces = {} end | 
| yellowfive@57 | 661 	if not sv.namespaces[name] then | 
| yellowfive@57 | 662 		sv.namespaces[name] = {} | 
| yellowfive@57 | 663 	end | 
| yellowfive@57 | 664 | 
| yellowfive@57 | 665 	local newDB = initdb(sv.namespaces[name], defaults, self.keys.profile, nil, self) | 
| yellowfive@57 | 666 | 
| yellowfive@57 | 667 	if not self.children then self.children = {} end | 
| yellowfive@57 | 668 	self.children[name] = newDB | 
| yellowfive@57 | 669 	return newDB | 
| yellowfive@57 | 670 end | 
| yellowfive@57 | 671 | 
| yellowfive@57 | 672 --- Returns an already existing namespace from the database object. | 
| yellowfive@57 | 673 -- @param name The name of the new namespace | 
| yellowfive@57 | 674 -- @param silent if true, the addon is optional, silently return nil if its not found | 
| yellowfive@57 | 675 -- @usage | 
| yellowfive@57 | 676 -- local namespace = self.db:GetNamespace('namespace') | 
| yellowfive@57 | 677 -- @return the namespace object if found | 
| yellowfive@57 | 678 function DBObjectLib:GetNamespace(name, silent) | 
| yellowfive@57 | 679 	if type(name) ~= "string" then | 
| yellowfive@57 | 680 		error("Usage: AceDBObject:GetNamespace(name): 'name' - string expected.", 2) | 
| yellowfive@57 | 681 	end | 
| yellowfive@57 | 682 	if not silent and not (self.children and self.children[name]) then | 
| yellowfive@57 | 683 		error ("Usage: AceDBObject:GetNamespace(name): 'name' - namespace does not exist.", 2) | 
| yellowfive@57 | 684 	end | 
| yellowfive@57 | 685 	if not self.children then self.children = {} end | 
| yellowfive@57 | 686 	return self.children[name] | 
| yellowfive@57 | 687 end | 
| yellowfive@57 | 688 | 
| yellowfive@57 | 689 --[[------------------------------------------------------------------------- | 
| yellowfive@57 | 690 	AceDB Exposed Methods | 
| yellowfive@57 | 691 ---------------------------------------------------------------------------]] | 
| yellowfive@57 | 692 | 
| yellowfive@57 | 693 --- Creates a new database object that can be used to handle database settings and profiles. | 
| yellowfive@57 | 694 -- By default, an empty DB is created, using a character specific profile. | 
| yellowfive@57 | 695 -- | 
| yellowfive@57 | 696 -- You can override the default profile used by passing any profile name as the third argument, | 
| yellowfive@57 | 697 -- or by passing //true// as the third argument to use a globally shared profile called "Default". | 
| yellowfive@57 | 698 -- | 
| yellowfive@57 | 699 -- Note that there is no token replacement in the default profile name, passing a defaultProfile as "char" | 
| yellowfive@57 | 700 -- will use a profile named "char", and not a character-specific profile. | 
| yellowfive@57 | 701 -- @param tbl The name of variable, or table to use for the database | 
| yellowfive@57 | 702 -- @param defaults A table of database defaults | 
| yellowfive@57 | 703 -- @param defaultProfile The name of the default profile. If not set, a character specific profile will be used as the default. | 
| yellowfive@57 | 704 -- You can also pass //true// to use a shared global profile called "Default". | 
| yellowfive@57 | 705 -- @usage | 
| yellowfive@57 | 706 -- -- Create an empty DB using a character-specific default profile. | 
| yellowfive@57 | 707 -- self.db = LibStub("AceDB-3.0"):New("MyAddonDB") | 
| yellowfive@57 | 708 -- @usage | 
| yellowfive@57 | 709 -- -- Create a DB using defaults and using a shared default profile | 
| yellowfive@57 | 710 -- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true) | 
| yellowfive@57 | 711 function AceDB:New(tbl, defaults, defaultProfile) | 
| yellowfive@57 | 712 	if type(tbl) == "string" then | 
| yellowfive@57 | 713 		local name = tbl | 
| yellowfive@57 | 714 		tbl = _G[name] | 
| yellowfive@57 | 715 		if not tbl then | 
| yellowfive@57 | 716 			tbl = {} | 
| yellowfive@57 | 717 			_G[name] = tbl | 
| yellowfive@57 | 718 		end | 
| yellowfive@57 | 719 	end | 
| yellowfive@57 | 720 | 
| yellowfive@57 | 721 	if type(tbl) ~= "table" then | 
| yellowfive@57 | 722 		error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'tbl' - table expected.", 2) | 
| yellowfive@57 | 723 	end | 
| yellowfive@57 | 724 | 
| yellowfive@57 | 725 	if defaults and type(defaults) ~= "table" then | 
| yellowfive@57 | 726 		error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaults' - table expected.", 2) | 
| yellowfive@57 | 727 	end | 
| yellowfive@57 | 728 | 
| yellowfive@57 | 729 	if defaultProfile and type(defaultProfile) ~= "string" and defaultProfile ~= true then | 
| yellowfive@57 | 730 		error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaultProfile' - string or true expected.", 2) | 
| yellowfive@57 | 731 	end | 
| yellowfive@57 | 732 | 
| yellowfive@57 | 733 	return initdb(tbl, defaults, defaultProfile) | 
| yellowfive@57 | 734 end | 
| yellowfive@57 | 735 | 
| yellowfive@57 | 736 -- upgrade existing databases | 
| yellowfive@57 | 737 for db in pairs(AceDB.db_registry) do | 
| yellowfive@57 | 738 	if not db.parent then | 
| yellowfive@57 | 739 		for name,func in pairs(DBObjectLib) do | 
| yellowfive@57 | 740 			db[name] = func | 
| yellowfive@57 | 741 		end | 
| yellowfive@57 | 742 	else | 
| yellowfive@57 | 743 		db.RegisterDefaults = DBObjectLib.RegisterDefaults | 
| yellowfive@57 | 744 		db.ResetProfile = DBObjectLib.ResetProfile | 
| yellowfive@57 | 745 	end | 
| yellowfive@57 | 746 end |