2 Mysql C++ traits for sqlgg
6 This is free and unencumbered software released into the public domain.
8 Anyone is free to copy, modify, publish, use, compile, sell, or
9 distribute this software, either in source code form or as a compiled
10 binary, for any purpose, commercial or non-commercial, and by any
13 For more information, please refer to <http://unlicense.org/>
16 #include <mysql/mysql.h>
17 #define SQLGG_STR(x) x
26 #if defined(SQLGG_DEBUG)
33 typedef std::string Text
;
38 template<class T
> T
* alloc(size_t const count
) { return (T
*)calloc(count
,sizeof(T
)); }
40 row_t(MYSQL_STMT
* stmt
, size_t count
) : count(count
), stmt(stmt
)
42 bind
= alloc
<MYSQL_BIND
>(count
);
43 error
= alloc
<my_bool
>(count
);
44 length
= alloc
<unsigned long>(count
);
45 is_null
= alloc
<my_bool
>(count
);
60 unsigned long* length
;
66 typedef MYSQL
* connection
;
68 static void get_column_Int(row r
, int index
, Int
& data
)
73 static void get_column_Text(row r
, int index
, Text
& data
)
75 unsigned long const& length
= r
.length
[index
];
76 MYSQL_BIND
& bind
= r
.bind
[index
];
81 bind
.buffer
= (void*)(data
.c_str());
82 bind
.buffer_length
= length
;
83 mysql_stmt_fetch_column(r
.stmt
, r
.bind
, index
, 0);
86 //data.resize(length);
89 static void bind_column_Int(row r
, int index
, Int
& data
)
91 MYSQL_BIND
& bind
= r
.bind
[index
];
94 bind
.buffer_type
= MYSQL_TYPE_LONG
;
95 bind
.buffer
= (void*)&data
;
96 bind
.is_null
= &r
.is_null
[index
];
97 bind
.length
= &r
.length
[index
];
98 bind
.error
= &r
.error
[index
];
101 static void bind_column_Text(row r
, int index
, Text
& data
)
103 MYSQL_BIND
& bind
= r
.bind
[index
];
105 bind
.buffer_type
= MYSQL_TYPE_STRING
;
107 bind
.buffer_length
= 0;
108 bind
.is_null
= &r
.is_null
[index
];
109 bind
.length
= &r
.length
[index
];
110 bind
.error
= &r
.error
[index
];
113 static void set_param(row r
, const Text
& val
, int index
)
115 MYSQL_BIND
& bind
= r
.bind
[index
];
117 r
.length
[index
] = val
.size();
118 bind
.length
= &r
.length
[index
];
119 bind
.buffer_length
= val
.size();
120 bind
.buffer_type
= MYSQL_TYPE_STRING
;
121 bind
.buffer
= (void*)val
.c_str();
124 static void set_param(row r
, const Int
& val
, int index
)
126 MYSQL_BIND
& bind
= r
.bind
[index
];
128 bind
.buffer_type
= MYSQL_TYPE_LONG
;
129 bind
.buffer
= (void*)&val
;
135 mysql_stmt(MYSQL_STMT
* stmt
) : stmt(stmt
)
141 if (stmt
) mysql_stmt_close(stmt
);
145 virtual ~mysql_stmt()
151 mysql_stmt& operator=(MYSQL_STMT* v)
158 operator MYSQL_STMT
*()
169 void set_params(row
) {}
191 statement(connection aDb
, char const* sql
) : db(aDb
), sql(sql
), stmt(mysql_stmt_init(aDb
))
205 #if defined(SQLGG_DEBUG)
206 fprintf(stderr
, " mysql_stmt_init(), out of memory\n");
211 if (mysql_stmt_prepare(stmt
, sql
, strlen(sql
)))
213 #if defined(SQLGG_DEBUG)
214 fprintf(stderr
, " mysql_stmt_prepare(), failed\n");
215 fprintf(stderr
, " %s\n", mysql_stmt_error(stmt
));
224 template<class T
, class Binder
, class Params
>
225 bool select(T result
, Binder binder
, Params params
)
229 if (Params::count
!= mysql_stmt_param_count(stmt
))
231 #if defined(SQLGG_DEBUG)
232 fprintf(stderr
, " wrong params count %u != %lu\n",Params::count
,mysql_stmt_param_count(stmt
));
236 if (Binder::count
!= mysql_stmt_field_count(stmt
))
238 #if defined(SQLGG_DEBUG)
239 fprintf(stderr
, " wrong number of columns %u != %u\n",Binder::count
,mysql_stmt_field_count(stmt
));
244 row_t
r_params(stmt
,Params::count
);
245 params
.set_params(r_params
);
247 if (mysql_stmt_bind_param(stmt
, r_params
.bind
))
249 #if defined(SQLGG_DEBUG)
250 fprintf(stderr
, " mysql_stmt_bind_param() failed\n");
251 fprintf(stderr
, " %s\n", mysql_stmt_error(stmt
));
256 if (mysql_stmt_execute(stmt
))
258 #if defined(SQLGG_DEBUG)
259 fprintf(stderr
, " mysql_stmt_execute(), failed\n");
260 fprintf(stderr
, " %s\n", mysql_stmt_error(stmt
));
265 row_t
r(stmt
,Binder::count
);
267 if (0 != Binder::count
)
271 if (mysql_stmt_bind_result(stmt
, r
.bind
))
273 #if defined(SQLGG_DEBUG)
274 fprintf(stderr
, " mysql_stmt_bind_result() failed\n");
275 fprintf(stderr
, " %s\n", mysql_stmt_error(stmt
));
283 int res
= mysql_stmt_fetch(stmt
);
284 if (0 != res
&& MYSQL_DATA_TRUNCATED
!= res
) break;
285 binder
.get(r
,result
);
291 template<class Params
>
292 bool execute(Params params
)
295 return select(dummy
,no_binder
<int>(),params
);