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
29 typedef std::string Text
;
34 template<class T
> T
* alloc(size_t const count
) { return (T
*)calloc(count
,sizeof(T
)); }
36 row_t(MYSQL_STMT
* stmt
, size_t count
) : count(count
), stmt(stmt
)
38 bind
= alloc
<MYSQL_BIND
>(count
);
39 error
= alloc
<my_bool
>(count
);
40 length
= alloc
<unsigned long>(count
);
41 is_null
= alloc
<my_bool
>(count
);
56 unsigned long* length
;
62 typedef MYSQL
* connection
;
64 static void get_column_Int(row r
, int index
, Int
& data
)
69 static void get_column_Text(row r
, int index
, Text
& data
)
71 unsigned long const& length
= r
.length
[index
];
72 MYSQL_BIND
& bind
= r
.bind
[index
];
77 bind
.buffer
= (void*)(data
.c_str());
78 bind
.buffer_length
= length
;
79 mysql_stmt_fetch_column(r
.stmt
, r
.bind
, index
, 0);
82 //data.resize(length);
85 static void bind_column_Int(row r
, int index
, Int
& data
)
87 MYSQL_BIND
& bind
= r
.bind
[index
];
90 bind
.buffer_type
= MYSQL_TYPE_LONG
;
91 bind
.buffer
= (void*)&data
;
92 bind
.is_null
= &r
.is_null
[index
];
93 bind
.length
= &r
.length
[index
];
94 bind
.error
= &r
.error
[index
];
97 static void bind_column_Text(row r
, int index
, Text
& data
)
99 MYSQL_BIND
& bind
= r
.bind
[index
];
101 bind
.buffer_type
= MYSQL_TYPE_STRING
;
103 bind
.buffer_length
= 0;
104 bind
.is_null
= &r
.is_null
[index
];
105 bind
.length
= &r
.length
[index
];
106 bind
.error
= &r
.error
[index
];
109 static void set_param(row r
, const Text
& val
, int index
)
111 MYSQL_BIND
& bind
= r
.bind
[index
];
113 r
.length
[index
] = val
.size();
114 bind
.length
= &r
.length
[index
];
115 bind
.buffer_length
= val
.size();
116 bind
.buffer_type
= MYSQL_TYPE_STRING
;
117 bind
.buffer
= (void*)val
.c_str();
120 static void set_param(row r
, const Int
& val
, int index
)
122 MYSQL_BIND
& bind
= r
.bind
[index
];
124 bind
.buffer_type
= MYSQL_TYPE_LONG
;
125 bind
.buffer
= (void*)&val
;
131 mysql_stmt(MYSQL_STMT
* stmt
) : stmt(stmt
)
137 if (stmt
) mysql_stmt_close(stmt
);
141 virtual ~mysql_stmt()
147 mysql_stmt& operator=(MYSQL_STMT* v)
154 operator MYSQL_STMT
*()
165 void set_params(row
) {}
187 statement(connection aDb
, char const* sql
) : db(aDb
), sql(sql
), stmt(mysql_stmt_init(aDb
))
201 #if defined(SQLGG_DEBUG)
202 fprintf(stderr
, " mysql_stmt_init(), out of memory\n");
207 if (mysql_stmt_prepare(stmt
, sql
, strlen(sql
)))
209 #if defined(SQLGG_DEBUG)
210 fprintf(stderr
, " mysql_stmt_prepare(), failed\n");
211 fprintf(stderr
, " %s\n", mysql_stmt_error(stmt
));
220 template<class T
, class Binder
, class Params
>
221 bool select(T result
, Binder binder
, Params params
)
225 if (Params::count
!= mysql_stmt_param_count(stmt
))
227 #if defined(SQLGG_DEBUG)
228 fprintf(stderr
, " wrong params count %u != %lu\n",Params::count
,mysql_stmt_param_count(stmt
));
232 if (Binder::count
!= mysql_stmt_field_count(stmt
))
234 #if defined(SQLGG_DEBUG)
235 fprintf(stderr
, " wrong number of columns %u != %u\n",Binder::count
,mysql_stmt_field_count(stmt
));
240 row_t
r_params(stmt
,Params::count
);
241 params
.set_params(r_params
);
243 if (mysql_stmt_bind_param(stmt
, r_params
.bind
))
245 #if defined(SQLGG_DEBUG)
246 fprintf(stderr
, " mysql_stmt_bind_param() failed\n");
247 fprintf(stderr
, " %s\n", mysql_stmt_error(stmt
));
252 if (mysql_stmt_execute(stmt
))
254 #if defined(SQLGG_DEBUG)
255 fprintf(stderr
, " mysql_stmt_execute(), failed\n");
256 fprintf(stderr
, " %s\n", mysql_stmt_error(stmt
));
261 row_t
r(stmt
,Binder::count
);
263 if (0 != Binder::count
)
267 if (mysql_stmt_bind_result(stmt
, r
.bind
))
269 #if defined(SQLGG_DEBUG)
270 fprintf(stderr
, " mysql_stmt_bind_result() failed\n");
271 fprintf(stderr
, " %s\n", mysql_stmt_error(stmt
));
279 int res
= mysql_stmt_fetch(stmt
);
280 if (0 != res
&& MYSQL_DATA_TRUNCATED
!= res
) break;
281 binder
.get(r
,result
);
287 template<class Params
>
288 bool execute(Params params
)
291 return select(dummy
,no_binder
<int>(),params
);