+pthread_mutex_t results_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+class MySQLresult : public SQLresult
+{
+ int currentrow;
+ //std::vector<std::map<std::string,std::string> > results;
+ std::vector<std::string> colnames;
+ std::vector<SQLfieldList> fieldlists;
+ SQLfieldMap* fieldmap;
+ int rows;
+ int cols;
+ public:
+
+ MySQLresult(Module* self, Module* to, MYSQL_RES* res, int affected_rows, unsigned int id) : SQLresult(self, to, id), currentrow(0), fieldmap(NULL)
+ {
+ /* A number of affected rows from from mysql_affected_rows.
+ */
+ log(DEBUG,"Created new MySQLresult of non-error type");
+ fieldlists.clear();
+ rows = 0;
+ if (affected_rows >= 1)
+ {
+ rows = affected_rows;
+ fieldlists.resize(rows);
+ }
+ unsigned int field_count;
+ if (res)
+ {
+ MYSQL_ROW row;
+ int n = 0;
+ while ((row = mysql_fetch_row(res)))
+ {
+ if (fieldlists.size() < (unsigned int)rows+1)
+ {
+ fieldlists.resize(fieldlists.size()+1);
+ }
+ field_count = 0;
+ MYSQL_FIELD *fields = mysql_fetch_fields(res);
+ if(mysql_num_fields(res) == 0)
+ break;
+ if (fields && mysql_num_fields(res))
+ {
+ colnames.clear();
+ while (field_count < mysql_num_fields(res))
+ {
+ std::string a = (fields[field_count].name ? fields[field_count].name : "");
+ std::string b = (row[field_count] ? row[field_count] : "");
+ SQLfield sqlf(b, !row[field_count]);
+ colnames.push_back(a);
+ fieldlists[n].push_back(sqlf);
+ field_count++;
+ }
+ n++;
+ }
+ rows++;
+ }
+ cols = mysql_num_fields(res);
+ mysql_free_result(res);
+ }
+ cols = field_count;
+ log(DEBUG, "Created new MySQL result; %d rows, %d columns", rows, cols);
+ }
+
+ MySQLresult(Module* self, Module* to, SQLerror e, unsigned int id) : SQLresult(self, to, id), currentrow(0)
+ {
+ rows = 0;
+ cols = 0;
+ error = e;
+ log(DEBUG,"Created new MySQLresult of error type");
+ }
+
+ ~MySQLresult()
+ {
+ }
+
+ virtual int Rows()
+ {
+ return rows;
+ }
+
+ virtual int Cols()
+ {
+ return cols;
+ }
+
+ virtual std::string ColName(int column)
+ {
+ if (column < (int)colnames.size())
+ {
+ return colnames[column];
+ }
+ else
+ {
+ throw SQLbadColName();
+ }
+ return "";
+ }
+
+ virtual int ColNum(const std::string &column)
+ {
+ for (unsigned int i = 0; i < colnames.size(); i++)
+ {
+ if (column == colnames[i])
+ return i;
+ }
+ throw SQLbadColName();
+ return 0;
+ }
+
+ virtual SQLfield GetValue(int row, int column)
+ {
+ if ((row >= 0) && (row < rows) && (column >= 0) && (column < cols))
+ {
+ return fieldlists[row][column];
+ }
+
+ log(DEBUG,"Danger will robinson, we don't have row %d, column %d!", row, column);
+ throw SQLbadColName();
+
+ /* XXX: We never actually get here because of the throw */
+ return SQLfield("",true);
+ }
+
+ virtual SQLfieldList& GetRow()
+ {
+ return fieldlists[currentrow];
+ }
+
+ virtual SQLfieldMap& GetRowMap()
+ {
+ fieldmap = new SQLfieldMap();
+
+ for (int i = 0; i < cols; i++)
+ {
+ fieldmap->insert(std::make_pair(colnames[cols],GetValue(currentrow, i)));
+ }
+ currentrow++;
+
+ return *fieldmap;
+ }
+
+ virtual SQLfieldList* GetRowPtr()
+ {
+ return &fieldlists[currentrow++];
+ }
+
+ virtual SQLfieldMap* GetRowMapPtr()
+ {
+ fieldmap = new SQLfieldMap();
+
+ for (int i = 0; i < cols; i++)
+ {
+ fieldmap->insert(std::make_pair(colnames[cols],GetValue(currentrow, i)));
+ }
+ currentrow++;
+
+ return fieldmap;
+ }
+
+ virtual void Free(SQLfieldMap* fm)
+ {
+ delete fm;
+ }
+
+ virtual void Free(SQLfieldList* fl)
+ {
+ /* XXX: Yes, this is SUPPOSED to do nothing, we
+ * dont want to free our fieldlist until we
+ * destruct the object. Unlike the pgsql module,
+ * we only have the one.
+ */
+ }
+};
+
+class SQLConnection;
+
+void NotifyMainThread(SQLConnection* connection_with_new_result);
+