summaryrefslogtreecommitdiff
path: root/libmysqlpp/selectcommand.cpp
blob: b361fb1d6c434f4ea276470809a271cb5dd1fdf2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include "selectcommand.h"
#include "connection.h"
#include "column.h"
#include "error.h"
#include <string.h>

MySQL::SelectCommand::SelectCommand(const Connection * conn, const std::string & sql) :
	DB::Command(sql),
	DB::SelectCommand(sql),
	MySQL::Command(conn, sql),
	executed(false)
{
}

void
MySQL::SelectCommand::execute()
{
	if (!executed) {
		bindParams();
		fields.resize(mysql_stmt_field_count(stmt));
		for (Binds::iterator i = fields.begin(); i != fields.end(); ++i) {
			memset(&*i, 0, sizeof(MYSQL_BIND));
		}
		MYSQL_RES * prepare_meta_result = mysql_stmt_result_metadata(stmt);
		MYSQL_FIELD * fieldDefs = mysql_fetch_fields(prepare_meta_result);
		for (unsigned int i = 0; i < fields.size(); i += 1) {
			switch (fieldDefs[i].type) {
				case MYSQL_TYPE_TINY:
				case MYSQL_TYPE_SHORT:
				case MYSQL_TYPE_LONG:
				case MYSQL_TYPE_INT24:
				case MYSQL_TYPE_LONGLONG:
				case MYSQL_TYPE_YEAR:
					columns.insert(boost::shared_ptr<ColumnBase>(new Column<int64_t, MYSQL_TYPE_LONGLONG>(fieldDefs[i].name, i, &fields[i])));
					break;
				case MYSQL_TYPE_DECIMAL:
				case MYSQL_TYPE_NEWDECIMAL:
				case MYSQL_TYPE_FLOAT:
				case MYSQL_TYPE_DOUBLE:
					columns.insert(boost::shared_ptr<ColumnBase>(new Column<double, MYSQL_TYPE_DOUBLE>(fieldDefs[i].name, i, &fields[i])));
					break;
				case MYSQL_TYPE_TIMESTAMP:
				case MYSQL_TYPE_DATE:
				case MYSQL_TYPE_DATETIME:
					columns.insert(boost::shared_ptr<ColumnBase>(new Column<MYSQL_TIME, MYSQL_TYPE_DATETIME>(fieldDefs[i].name, i, &fields[i])));
					break;
				case MYSQL_TYPE_TIME:
					columns.insert(boost::shared_ptr<ColumnBase>(new Column<MYSQL_TIME, MYSQL_TYPE_TIME>(fieldDefs[i].name, i, &fields[i])));
					break;
				case MYSQL_TYPE_STRING:
				case MYSQL_TYPE_VAR_STRING:
					columns.insert(boost::shared_ptr<ColumnBase>(new StringColumn(fieldDefs[i].name, i, &fields[i], fieldDefs[i].length)));
					break;
				case MYSQL_TYPE_NULL:
					columns.insert(boost::shared_ptr<ColumnBase>(new NullColumn(fieldDefs[i].name, i, &fields[i])));
					break;
				case MYSQL_TYPE_BIT:
				case MYSQL_TYPE_BLOB:
				case MYSQL_TYPE_SET:
				case MYSQL_TYPE_ENUM:
				case MYSQL_TYPE_GEOMETRY:
				default:
					mysql_free_result(prepare_meta_result);
					throw Error("Unexpected type");
			}
		}
		mysql_free_result(prepare_meta_result);
		if (mysql_stmt_bind_result(stmt, &fields.front())) {
			throw Error(mysql_stmt_error(stmt));
		}
		if (mysql_stmt_execute(stmt)) {
			throw Error(mysql_stmt_error(stmt));
		}
		if (mysql_stmt_store_result(stmt)) {
			throw Error(mysql_stmt_error(stmt));
		}
		executed = true;
	}
}

bool
MySQL::SelectCommand::fetch()
{
	execute();
	switch (mysql_stmt_fetch(stmt)) {
		case 0:
			return true;
		case MYSQL_NO_DATA:
			return false;
		default:
			throw Error(mysql_stmt_error(stmt));
	}
}

const DB::Column&
MySQL::SelectCommand::operator[](unsigned int n) const
{
	if (n < columns.size()) {
		return **columns.get<0>().find(n);
	}
	throw Error();
}

const DB::Column&
MySQL::SelectCommand::operator[](const Glib::ustring & n) const
{
	typedef Columns::nth_index<1>::type CbyName;
	CbyName::iterator i = columns.get<1>().find(n);
	if (i != columns.get<1>().end()) {
		return **i;
	}
	throw Error();
}

unsigned int
MySQL::SelectCommand::getOrdinal(const Glib::ustring & n) const
{
	typedef Columns::nth_index<1>::type CbyName;
	CbyName::iterator i = columns.get<1>().find(n);
	if (i != columns.get<1>().end()) {
		return (*i)->colNo;
	}
	throw Error();
}

unsigned int
MySQL::SelectCommand::columnCount() const
{
	return fields.size();
}