1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "../pd_lib/pds_common.h"
19 #include "pds_attribute.h"
21 #include "pds_table.h"
22 #include "pds_database.h"
23 #include "../pd_lib/db_description_parser.h"
25 #include <nel/misc/debug.h>
28 using namespace NLMISC
;
32 CAttribute::~CAttribute()
34 //PDS_DEBUG("delete()");
39 * Initialize attribute using a full xml node
41 bool CAttribute::init(CDatabase
*root
, CTable
* parent
, const CAttributeNode
& attribute
)
44 setParentLogger(parent
);
49 _Name
= attribute
.Name
;
52 _MetaType
= attribute
.MetaType
;
53 _TypeId
= attribute
.TypeId
;
59 const CType
* type
= _Root
->getType(_TypeId
);
62 PDS_WARNING("init(): unknown type '%d'", _TypeId
);
66 _DataType
= type
->getDataType();
71 _DataType
= PDS_UnknownDataType
;
75 _DataType
= PDS_Index
;
76 _ReferencedAttribute
= attribute
.Reference
;
80 _DataType
= PDS_Index
;
81 _ReferencedAttribute
= attribute
.Reference
;
86 const CType
* index
= _Root
->getType(attribute
.Index
);
87 if (index
== NULL
|| !index
->isIndex())
89 PDS_WARNING("init(): type '%d' unknown or not an index", attribute
.Index
);
93 _IndexId
= attribute
.Index
;
95 const CType
* type
= _Root
->getType(_TypeId
);
98 PDS_WARNING("init(): unknown type '%d'", _TypeId
);
102 _DataType
= type
->getDataType();
108 const CType
* type
= _Root
->getType(attribute
.Index
);
109 if (type
== NULL
|| !type
->isIndex())
111 PDS_WARNING("init(): type '%d' unknown or not an index", attribute
.Index
);
115 _IndexId
= attribute
.Index
;
116 _DataType
= PDS_UnknownDataType
;
122 const CType
* type
= _Root
->getType(attribute
.Index
);
123 if (type
== NULL
|| !type
->isIndex())
125 PDS_WARNING("init(): type '%d' unknown or not an index", attribute
.Index
);
129 _IndexId
= attribute
.Index
;
130 _DataType
= PDS_Index
;
131 _ReferencedAttribute
= attribute
.Reference
;
132 _AllowNull
= attribute
.AllowNull
;
137 _DataType
= PDS_List
;
138 _ReferencedAttribute
= attribute
.Reference
;
148 * Build columns for this attribute
150 bool CAttribute::buildColumns()
152 vector
<CColumn
>& columns
= _Parent
->_Columns
;
154 _Offset
= (uint32
)columns
.size();
161 column
._Parent
= this;
162 column
._Root
= _Root
;
163 column
._Id
= (uint32
)columns
.size();
164 column
._Name
= _Name
;
165 column
._MetaType
= PDS_Type
;
166 column
._DataType
= _DataType
;
167 column
._TypeId
= _TypeId
;
168 const CType
* type
= _Root
->getType(_TypeId
);
171 PDS_WARNING("init(): unknown type '%d'", _TypeId
);
174 column
._ByteSize
= type
->getByteSize();
176 columns
.push_back(column
);
182 CTable
* sub
= const_cast<CTable
*>(_Root
->getTable(_TypeId
));
184 if (sub
== NULL
|| !sub
->buildColumns())
188 for (i
=0; i
<sub
->_Columns
.size(); ++i
)
190 CColumn column
= sub
->_Columns
[i
];
191 column
._Parent
= this;
192 column
._Root
= _Root
;
193 column
._Id
= (uint32
)columns
.size();
194 column
._Name
= _Name
+"."+column
._Name
;
196 columns
.push_back(column
);
206 column
._Parent
= this;
207 column
._Root
= _Root
;
208 column
._Id
= (uint32
)columns
.size();
209 column
._Name
= _Name
;
210 column
._MetaType
= _MetaType
;
211 column
._DataType
= _DataType
;
212 column
._TypeId
= _TypeId
;
213 column
._ByteSize
= getStandardByteSize(column
._DataType
);
215 columns
.push_back(column
);
221 const CType
* type
= _Root
->getType(_TypeId
);
222 const CType
* index
= _Root
->getType(_IndexId
);
226 PDS_WARNING("init(): unknown type '%d'", _TypeId
);
230 if (index
== NULL
|| !index
->isIndex())
232 PDS_WARNING("buildColumns(): type '%d' unknown or not an index", _IndexId
);
237 for (i
=0; i
<index
->getIndexSize(); ++i
)
240 column
._Parent
= this;
241 column
._Root
= _Root
;
242 column
._Id
= (uint32
)columns
.size();
243 column
._Name
= _Name
+"["+index
->getIndexName(i
)+"]";
244 column
._MetaType
= PDS_Type
;
245 column
._DataType
= _DataType
;
246 column
._TypeId
= _TypeId
;
247 column
._ByteSize
= type
->getByteSize();
249 columns
.push_back(column
);
256 CTable
* sub
= const_cast<CTable
*>(_Root
->getTable(_TypeId
));
257 const CType
* index
= _Root
->getType(_IndexId
);
259 if (sub
== NULL
|| sub
== NULL
|| !sub
->buildColumns())
261 PDS_WARNING("buildColumns(): unknown table '%d' or failed to build its columns", _TypeId
);
265 if (index
== NULL
|| index
== NULL
|| !index
->isIndex())
267 PDS_WARNING("buildColumns(): type '%d' unknown or not an index", _IndexId
);
272 for (i
=0; i
<index
->getIndexSize(); ++i
)
275 for (j
=0; j
<sub
->_Columns
.size(); ++j
)
277 CColumn column
= sub
->_Columns
[j
];
278 column
._Parent
= this;
279 column
._Root
= _Root
;
280 column
._Id
= (uint32
)columns
.size();
281 column
._Name
= _Name
+"["+index
->getIndexName(i
)+"]"+"."+column
._Name
;
283 columns
.push_back(column
);
291 const CType
* index
= _Root
->getType(_IndexId
);
293 if (index
== NULL
|| !index
->isIndex())
295 PDS_WARNING("buildColumns(): type '%d' unknown or not an index", _IndexId
);
300 for (i
=0; i
<index
->getIndexSize(); ++i
)
303 column
._Parent
= this;
304 column
._Root
= _Root
;
305 column
._Id
= (uint32
)columns
.size();
306 column
._Name
= _Name
+"["+index
->getIndexName(i
)+"]";;
307 column
._MetaType
= PDS_ForwardRef
;
308 column
._DataType
= _DataType
;
309 column
._TypeId
= _TypeId
;
310 column
._ByteSize
= getStandardByteSize(column
._DataType
);
312 columns
.push_back(column
);
318 PDS_WARNING("buildColumns(): attribute '%s' metatype is unknown", _Name
.c_str());
323 _Columns
= (uint32
)columns
.size() - _Offset
;
330 * Compute back reference key
332 bool CAttribute::computeBackRefKey()
334 if (_MetaType
== PDS_BackRef
)
336 const CTable
* parentTable
= _Root
->getTable(_TypeId
);
337 const CAttribute
* parentAttribute
= parentTable
->getAttribute(_ReferencedAttribute
);
339 // should check parentAttribute is a forward reference of any kind
341 const CTable
* childTable
= _Root
->getTable(parentAttribute
->getTypeId());
343 _Key
= childTable
->getKey();
345 else if (_MetaType
== PDS_ArrayRef
|| _MetaType
== PDS_Set
)
347 const CTable
* childTable
= _Root
->getTable(_TypeId
);
348 const CAttribute
* childAttribute
= childTable
->getAttribute(_ReferencedAttribute
);
350 if (childAttribute
== NULL
)
352 PDS_WARNING("computeBackRefKey(): failed, child backref not initialised");
356 if (childAttribute
->getMetaType() != PDS_BackRef
)
358 PDS_WARNING("computeBackRefKey(): failed, child backref actually not a backref");
362 _Key
= childTable
->getKey();
363 if (_Key
== INVALID_TYPE_ID
)
365 PDS_WARNING("computeBackRefKey(): failed, child key is invalid");
369 const CAttribute
* keyAttribute
= childTable
->getAttribute(_Key
);
371 if (keyAttribute
== NULL
)
373 PDS_WARNING("computeBackRefKey(): failed, child key '%d' attribute cannot be found", _Key
);
377 if (_Key
!= childAttribute
->getBackRefKey())
379 PDS_WARNING("computeBackRefKey(): failed, child backref key '%d' mismatch child key '%d'", childAttribute
->getBackRefKey(), _Key
);