EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
EVEDBUtils.cpp
Go to the documentation of this file.
1 /*
2  ------------------------------------------------------------------------------------
3  LICENSE:
4  ------------------------------------------------------------------------------------
5  This file is part of EVEmu: EVE Online Server Emulator
6  Copyright 2006 - 2021 The EVEmu Team
7  For the latest information visit https://evemu.dev
8  ------------------------------------------------------------------------------------
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU Lesser General Public License as published by the Free Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  version.
13 
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public License along with
19  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20  Place - Suite 330, Boston, MA 02111-1307, USA, or go to
21  http://www.gnu.org/copyleft/lesser.txt.
22  ------------------------------------------------------------------------------------
23  Author: Zhur
24  Updates: Allan
25 */
26 
27 #include "eve-common.h"
28 
29 #include "database/EVEDBUtils.h"
30 #include "packets/General.h"
32 #include "python/PyVisitor.h"
33 #include "python/PyRep.h"
34 
35 
37 {
38  /* check for valid column */
39  if (row.IsNull(index))
40  return PyStatic.NewNone(); // this doesnt work right. client still sees this as 0 instead of None
41 
42  switch(row.ColumnType(index)) {
43  case DBTYPE_I1:
44  case DBTYPE_UI1:
45  case DBTYPE_I2:
46  case DBTYPE_UI2:
47  case DBTYPE_I4:
48  case DBTYPE_UI4:
49  return new PyInt( row.GetInt( index ) );
50 
51  case DBTYPE_I8:
52  case DBTYPE_UI8:
53  return new PyLong( row.GetInt64( index ) );
54 
55  case DBTYPE_R8:
56  case DBTYPE_R4:
57  return new PyFloat( row.GetDouble( index ) );
58 
59  case DBTYPE_BOOL:
60  return new PyBool( row.GetBool(index) );
61 
62  case DBTYPE_STR:
63  return new PyString( row.GetText( index ), row.ColumnLength( index ) );
64 
65  case DBTYPE_WSTR:
66  return new PyWString( row.GetText( index ), row.ColumnLength( index ) );
67 
68  case DBTYPE_BYTES: {
69  const uint8* data = (const uint8*)row.GetText( index );
70  const uint32 len = row.ColumnLength( index );
71  return new PyBuffer( data, data + len );
72  }
73 
74  default: {
75  sLog.Error( "DBColumnToPyRep", "invalid column type: %u", row.ColumnType(index) );
76  return PyStatic.NewNone();
77  }
78  }
79 }
80 
82 {
83  uint32 cc = result.ColumnCount();
84 
85  PyDict *args = new PyDict();
86 
87  /* check if we have a empty query result and return a empty RowSet */
88  if (cc == 0 )
89  return new PyObject( "util.Rowset" , args );
90 
91  //list off the column names:
92  PyList *header = new PyList( cc );
93  for(uint32 r(0); r < cc; ++r)
94  header->SetItemString( r, result.ColumnName(r));
95  args->SetItemString("header", header);
96 
97  //RowClass:
98  args->SetItemString("RowClass", new PyToken("util.Row"));
99 
100  //lines:
101  PyList *rowlist = new PyList();
102  //add a line entry for each result row:
103  uint32 r(0);
104  DBResultRow row;
105  while(result.GetRow(row)) {
106  PyList *linedata = new PyList( cc );
107  for (r = 0; r < cc; ++r)
108  linedata->SetItem( r, DBColumnToPyRep(row, r) );
109  rowlist->AddItem(linedata);
110  }
111  args->SetItemString("lines", rowlist);
112 
113  return new PyObject( "util.Rowset" , args );
114 }
115 
117  uint32 cc = result.ColumnCount();
118  if(cc == 0)
119  return new PyTuple(0);
120 
121  PyTuple *res = new PyTuple(2);
122 
123  //list off the column names:
124  PyList *cols = new PyList(cc);
125  for(uint32 r(0); r < cc; ++r)
126  cols->SetItemString(r, result.ColumnName(r));
127  res->items[0] = cols;
128 
129  //add a line entry for each result row:
130  uint32 r(0);
131  DBResultRow row;
132  PyList *reslist = new PyList();
133  while(result.GetRow(row)) {
134  PyList *linedata = new PyList(cc);
135  for(r = 0; r < cc; ++r)
136  linedata->SetItem(r, DBColumnToPyRep(row, r));
137  reslist->items.push_back(linedata);
138  }
139  res->items[1] = reslist;
140 
141  return res;
142 }
143 
145  uint32 cc = result.ColumnCount();
146  uint32 key_index(0);
147 
148  for(key_index = 0; key_index < cc; ++key_index)
149  if(strcmp(key, result.ColumnName(key_index)) == 0)
150  break;
151 
152  if(key_index == cc)
153  {
154  sLog.Error("EVEDBUtils", "DBResultToIndexRowset | Failed to find key column '%s' in result for IndexRowset", key);
155  return nullptr;
156  }
157 
158  return DBResultToIndexRowset(result, key_index);
159 }
160 
162  uint32 cc = result.ColumnCount();
163 
164  //start building the IndexRowset
165  PyDict *args = new PyDict();
166 
167  if(cc == 0 || cc < key_index)
168  return new PyObject( "util.IndexRowset", args );
169 
170  //list off the column names:
171  PyList *header = new PyList(cc);
172  args->SetItemString("header", header);
173  for(uint32 i(0); i < cc; ++i)
174  header->SetItemString(i, result.ColumnName(i));
175 
176  //RowClass:
177  args->SetItemString("RowClass", new PyToken("util.Row"));
178  //idName:
179  args->SetItemString("idName", new PyString( result.ColumnName(key_index) ));
180 
181  //items:
182  PyDict *items = new PyDict();
183  //add a line entry for each result row:
184  uint32 i(0);
185  DBResultRow row;
186  while(result.GetRow(row)) {
187  PyRep *key = DBColumnToPyRep(row, key_index);
188  PyList *line = new PyList(cc);
189  for(i = 0; i < cc; ++i)
190  line->SetItem(i, DBColumnToPyRep(row, i));
191 
192  items->SetItem(key, line);
193  }
194 
195  args->SetItemString("items", items);
196  return new PyObject( "util.IndexRowset", args );
197 }
198 
200  PyDict *args = new PyDict();
201  uint32 cc = row.ColumnCount();
202  for( uint32 r(0); r < cc; ++r )
203  args->SetItemString( row.ColumnName(r), DBColumnToPyRep(row, r));
204 
205  return new PyObject( "util.KeyVal", args );
206 }
207 
208 PyObject *DBRowToRow(DBResultRow &row, const char *type)
209 {
210  PyDict *args = new PyDict();
211 
212  //list off the column names:
213  uint32 cc = row.ColumnCount();
214  PyList *header = new PyList(cc);
215  for(uint32 r(0); r < cc; ++r)
216  header->SetItemString(r, row.ColumnName(r));
217 
218  args->SetItemString("header", header);
219 
220  //lines:
221  PyList *rowlist = new PyList(cc);
222  //add a line entry for the row:
223  for(uint32 r(0); r < cc; ++r)
224  rowlist->SetItem(r, DBColumnToPyRep(row, r));
225 
226  args->SetItemString("line", rowlist);
227 
228  return new PyObject( type, args );
229 }
230 
231 PyTuple *DBResultToRowList(DBQueryResult &result, const char *type) {
232  uint32 cc = result.ColumnCount();
233  if(cc == 0)
234  return(new PyTuple(0));
235 
236  PyList *cols = new PyList(cc);
237  //list off the column names:
238  for(uint32 r(0); r < cc; ++r)
239  cols->SetItemString(r, result.ColumnName(r));
240 
241  PyTuple *res = new PyTuple(2);
242  res->SetItem( 0, cols );
243 
244  //add a line entry for each result row:
245  DBResultRow row;
246  PyList *reslist = new PyList();
247  while(result.GetRow(row)) {
248  //this could be more efficient by not building the column list each time, but cloning it instead.
249  PyObject *o = DBRowToRow(row, type);
250  reslist->items.push_back(o);
251  }
252  res->SetItem( 1, reslist );
253 
254  return res;
255 }
256 
257 PyDict *DBResultToIntRowDict(DBQueryResult &result, uint32 key_index, const char *type) {
258  PyDict *res = new PyDict();
259  //add a line entry for each result row:
260  DBResultRow row;
261  while (result.GetRow(row)) {
262  //this could be more efficient by not building the column list each time, but cloning it instead.
263  PyObject *r = DBRowToRow(row, type);
264  int32 k = row.GetInt(key_index);
265  if (k == 0)
266  continue; //likely a non-integer key
267  res->SetItem(new PyInt(k), r);
268  }
269 
270  return res;
271 }
272 
274  PyDict *res = new PyDict();
275  //add a line entry for each result row:
276  DBResultRow row;
277  while(result.GetRow(row)) {
278  if (row.IsNull(0))
279  continue; //no working with NULL keys...
280  int32 k = row.GetInt(0);
281  if (k == 0)
282  continue; //likely a non-integer key
283  if (row.IsNull(1))
284  res->SetItem( new PyInt(k), PyStatic.NewNone() );
285  else
286  res->SetItem( new PyInt(k), new PyInt(row.GetInt(1)) );
287  }
288 
289  return res;
290 }
291 
292 void FillPackedRow( const DBResultRow& row, PyPackedRow* into )
293 {
294  uint32 cc = row.ColumnCount();
295  for( uint32 i(0); i < cc; ++i )
296  into->SetField( i, DBColumnToPyRep( row, i ) );
297 }
298 
300 {
301  PyPackedRow* res = new PyPackedRow( header );
302  FillPackedRow( row, res );
303  return res;
304 }
305 
307 {
308  DBRowDescriptor *header = new DBRowDescriptor( result );
309  PyList * list = new PyList( result.GetRowCount() );
310 
311  uint32 i(0);
312  DBResultRow row;
313  while( result.GetRow(row) ) {
314  list->SetItem( i++, CreatePackedRow( row, header ) );
315  PyIncRef( header );
316  }
317 
318  PyDecRef( header );
319  return list;
320 }
321 
323 {
324  DBRowDescriptor * header = new DBRowDescriptor( result );
325  PyList * list = new PyList( result.GetRowCount() );
326 
327  DBResultRow row;
328  uint32 i(0);
329  while( result.GetRow(row) ) {
330  list->SetItem( i++, CreatePackedRow( row, header ) );
331  PyIncRef( header );
332  }
333 
334  PyTuple* res = new PyTuple(2);
335  res->SetItem( 0, header );
336  res->SetItem( 1, list );
337  return res;
338 }
339 
341 {
342  uint32 cc = result.ColumnCount();
343  uint32 key_index(0);
344 
345  for (key_index = 0; key_index < cc; ++key_index)
346  if (strcmp(key, result.ColumnName(key_index)) == 0)
347  break;
348 
349  if(key_index == cc)
350  {
351  sLog.Error("EVEDBUtils", "DBResultToPackedRowDict | Failed to find key column '%s' in result for CIndexRowset", key);
352  return NULL;
353  }
354 
355  return DBResultToPackedRowDict(result, key_index);
356 }
357 
359 {
360  DBRowDescriptor *header = new DBRowDescriptor( result );
361 
362  PyDict *res = new PyDict();
363 
364  DBResultRow row;
365  while( result.GetRow(row) ) {
366  res->SetItem( DBColumnToPyRep(row, key_index), CreatePackedRow( row, header ) );
367  PyIncRef( header );
368  }
369 
370  PyDecRef( header );
371  return res;
372 }
373 
374 /* Class structure
375  * PyClass
376  * PyTuple:2
377  * itr[0]:PyTuple:1
378  * itr[0]:PyClass
379  * PyString:"dbutil.CRowset"
380  * itr[1]:PyDict:1
381  * dict["header"]=PyClass
382  * PyTuple:2
383  * itr[0]:PyClass
384  * PyString:"blue.DBRowDescriptor"
385  * itr[1]:PyTuple:1
386  * itr[0]:PyTuple:N<Amount of cols>
387  * itr[0]:PyTuple:2
388  * itr[0]:PyString<FieldName>
389  * itr[1]:PyInt<FieldType> DBTYPE
390  * itr[N]:PyTuple:2
391  * itr[0]:PyString<FieldName>
392  * itr[1]:PyInt<FieldType> DBTYPE
393  * PyDict:0
394  * PyList:0
395  * PyDict:0
396  * PyList:N<Amount of rows>
397  * itr[N]:PyPackedRow
398  */
399 
400 /* this is a very monstrous implementation of a Python Class/Function call
401  */
403 {
405  DBRowDescriptor *header = new DBRowDescriptor( result );
406  CRowSet *rowset = new CRowSet( &header );
407 
408  DBResultRow row;
409  while( result.GetRow( row ) )
410  {
411  PyPackedRow* into = rowset->NewRow();
412  FillPackedRow( row, into );
413  }
414 
415  //PyDecRef( header );
416  return rowset;
417 }
418 
420 {
421  uint32 cc = result.ColumnCount();
422  uint32 key_index(0);
423 
424  for(key_index = 0; key_index < cc; key_index++)
425  if(strcmp(key, result.ColumnName(key_index)) == 0)
426  break;
427 
428  if(key_index == cc)
429  {
430  sLog.Error("EVEDBUtils", "DBResultToCIndexedRowset | Failed to find key column '%s' in result for CIndexRowset", key);
431  return NULL;
432  }
433 
434  return DBResultToCIndexedRowset(result, key_index);
435 }
436 
439  DBRowDescriptor *header = new DBRowDescriptor( result );
440  CIndexedRowSet *rowset = new CIndexedRowSet( &header );
441 
442  DBResultRow row;
443  while( result.GetRow( row ) )
444  {
445  PyPackedRow* into = rowset->NewRow( DBColumnToPyRep(row, key_index) );
446  FillPackedRow( row, into );
447  }
448 
449  //PyDecRef( header );
450  return rowset;
451 }
452 
454 {
455  DBRowDescriptor *header = new DBRowDescriptor( row );
456 
457  return CreatePackedRow( row, header );
458 }
459 
463 void DBResultToIntIntDict(DBQueryResult &result, std::map<int32, int32> &into) {
464  //add a line entry for each result row:
465  DBResultRow row;
466  while(result.GetRow(row)) {
467  if (row.IsNull(0))
468  continue; //no working with NULL keys...
469  int32 k = row.GetInt(0);
470  int32 v(0);
471  if (row.IsNull(1))
472  v = 0; //we can deal with assuming NULL == 0
473  else
474  v = row.GetInt(1);
475  into[k] = v;
476  }
477 }
478 
479 void DBResultToUIntUIntDict(DBQueryResult &result, std::map<uint32, uint32> &into) {
480  //add a line entry for each result row:
481  DBResultRow row;
482  while(result.GetRow(row)) {
483  if(row.IsNull(0))
484  continue; //no working with NULL keys...
485  uint32 k = row.GetUInt(0);
486  uint32 v(0);
487  if(row.IsNull(1))
488  v = 0; //we can deal with assuming NULL == 0
489  else
490  v = row.GetUInt(1);
491  into[k] = v;
492  }
493 }
494 
495 void DBResultToIntIntlistDict( DBQueryResult &result, std::map<int32, PyRep *> &into ) {
496  /* this builds a map from the int in result[0], to a list of each result[1]
497  * which is has the same result[0]. This function assumes the result is
498  * ORDER BY result[0]
499  */
500  uint32 last_key = 0xFFFFFFFF;
501 
502  PyList *l = NULL;
503 
504  DBResultRow row;
505  while( result.GetRow( row ) )
506  {
507  uint32 k = row.GetUInt(0);
508  if (k != last_key )
509  {
510  //watch for overwrite, no guarantee we are dealing with a key.
511  std::map<int32, PyRep *>::iterator res = into.find(k);
512  if (res != into.end() )
513  //log an error or warning?
514  PyDecRef( res->second );
515 
516  into[k] = l = new PyList();
517  last_key = k;
518  }
519 
520  l->AddItemInt( row.GetInt( 1 ) );
521  }
522 }
Base Python wire object.
Definition: PyRep.h:66
unsigned __int8 uint8
Definition: eve-compat.h:46
uint32 ColumnLength(uint32 index) const
Definition: dbcore.cpp:624
const char * GetText(uint32 index) const
Definition: dbcore.h:104
PyTuple * DBResultToPackedRowListTuple(DBQueryResult &result)
Definition: EVEDBUtils.cpp:322
PyObjectEx * DBResultToCRowset(DBQueryResult &result)
Definition: EVEDBUtils.cpp:402
Python string.
Definition: PyRep.h:430
int32 GetInt(uint32 index) const
Definition: dbcore.cpp:635
Python's dictionary.
Definition: PyRep.h:719
uint32 GetUInt(uint32 index) const
Definition: dbcore.cpp:658
double GetDouble(uint32 index) const
Definition: dbcore.cpp:693
void SetItemString(size_t index, const char *str)
Stores Python string.
Definition: PyRep.h:699
Python floating point number.
Definition: PyRep.h:292
Python wide string.
Definition: PyRep.h:475
PyObjectEx * DBResultToCIndexedRowset(DBQueryResult &result, const char *key)
Definition: EVEDBUtils.cpp:419
Python tuple.
Definition: PyRep.h:567
PyDict * DBResultToIntIntDict(DBQueryResult &result)
Definition: EVEDBUtils.cpp:273
void AddItem(PyRep *i)
Definition: PyRep.h:701
signed __int32 int32
Definition: eve-compat.h:49
* args
bool GetRow(DBResultRow &into)
Definition: dbcore.cpp:552
bool GetBool(uint32 index) const
Definition: dbcore.cpp:647
PyObject * DBRowToRow(DBResultRow &row, const char *type)
Definition: EVEDBUtils.cpp:208
Python boolean.
Definition: PyRep.h:323
#define sLog
Evaluates to a NewLog instance.
Definition: LogNew.h:250
Python extended object.
Definition: PyRep.h:861
void DBResultToIntIntlistDict(DBQueryResult &result, std::map< int32, PyRep * > &into)
Definition: EVEDBUtils.cpp:495
PyDict * DBResultToIntRowDict(DBQueryResult &result, uint32 key_index, const char *type)
Definition: EVEDBUtils.cpp:257
Python object.
Definition: PyRep.h:826
Python object "blue.DBRowDescriptor".
Definition: PyDatabase.h:41
uint32 ColumnCount() const
Definition: dbcore.h:76
void SetItem(size_t index, PyRep *object)
Stores Python object.
Definition: PyRep.h:610
Python object "dbutil.CRowset".
Definition: PyDatabase.h:124
PyPackedRow * NewRow(PyRep *key)
Definition: PyDatabase.cpp:191
storage_type items
Definition: PyRep.h:708
PyObject * DBResultToRowset(DBQueryResult &result)
Definition: EVEDBUtils.cpp:81
Python integer.
Definition: PyRep.h:231
void SetItem(size_t index, PyRep *object)
Stores Python object.
Definition: PyRep.h:682
const char * ColumnName(uint32 index) const
Definition: dbcore.h:114
PyTuple * DBResultToRowList(DBQueryResult &result, const char *type)
Definition: EVEDBUtils.cpp:231
PyTuple * DBResultToTupleSet(DBQueryResult &result)
Definition: EVEDBUtils.cpp:116
#define PyStatic
Definition: PyRep.h:1209
bool IsNull(uint32 index) const
Definition: dbcore.h:102
void AddItemInt(int32 intval)
Definition: PyRep.h:702
PyList * DBResultToPackedRowList(DBQueryResult &result)
Definition: EVEDBUtils.cpp:306
#define PyDecRef(op)
Definition: PyRep.h:57
const char * ColumnName(uint32 index) const
Definition: dbcore.cpp:569
unsigned __int32 uint32
Definition: eve-compat.h:50
#define PyIncRef(op)
Definition: PyRep.h:56
PyObject * DBResultToIndexRowset(DBQueryResult &result, const char *key)
Definition: EVEDBUtils.cpp:144
Python token (eg. class name).
Definition: PyRep.h:522
bool SetField(uint32 index, PyRep *value)
Definition: PyRep.cpp:1031
Python object "dbutil.CIndexedRowset".
Definition: PyDatabase.h:172
PyPackedRow * NewRow()
Definition: PyDatabase.cpp:132
size_t GetRowCount()
Definition: dbcore.h:72
PyPackedRow * DBRowToPackedRow(DBResultRow &row)
Definition: EVEDBUtils.cpp:453
Python buffer.
Definition: PyRep.h:382
Packed row.
Definition: PyRep.h:961
PyDict * DBResultToPackedRowDict(DBQueryResult &result, const char *key)
Definition: EVEDBUtils.cpp:340
storage_type items
Definition: PyRep.h:628
PyObject * DBRowToKeyVal(DBResultRow &row)
Definition: EVEDBUtils.cpp:199
typeID Spawn an NPC with the specified type text Search for items matching the specified query() type() key(value)-Send an OnRemoteMessage" ) COMMAND( setbpattr
uint32 ColumnCount() const
Definition: dbcore.h:113
void FillPackedRow(const DBResultRow &row, PyPackedRow *into)
Definition: EVEDBUtils.cpp:292
int64 GetInt64(uint32 index) const
Definition: dbcore.cpp:670
entityID heal the character with the entityID note giving you detailed ship status information gives a list of all dynamic entities and players and their destinyState in this bubble shows some current destiny variables save all items
void SetItem(PyRep *key, PyRep *value)
SetItem adds or sets a database entry.
Definition: PyRep.cpp:713
Python list.
Definition: PyRep.h:639
void SetItemString(const char *key, PyRep *value)
SetItemString adds or sets a database entry.
Definition: PyRep.h:812
PyRep * DBColumnToPyRep(const DBResultRow &row, uint32 index)
Definition: EVEDBUtils.cpp:36
DBTYPE ColumnType(uint32 index) const
Definition: dbcore.h:115
PyPackedRow * CreatePackedRow(const DBResultRow &row, DBRowDescriptor *header)
Definition: EVEDBUtils.cpp:299
Python long integer.
Definition: PyRep.h:261
void DBResultToUIntUIntDict(DBQueryResult &result, std::map< uint32, uint32 > &into)
Definition: EVEDBUtils.cpp:479