/examples/Mysql.winxed

http://github.com/NotFound/winxed · Unknown · 358 lines · 325 code · 33 blank · 0 comment · 0 complexity · 8b9c11e1923364d76659ecbe2fa074cc MD5 · raw file

  1. #! winxed
  2. // Test Mysql usage via NCI
  3. // Note:
  4. // null results from dlfuncs are checked in a convoluted way
  5. // to be able to work with buggy versions of parrot.
  6. namespace WinxedMysql
  7. {
  8. $include_const 'datatypes.pasm';
  9. // Severity and type of the exceptions explicitly thrown.
  10. const int ERROR = 2;
  11. const int TYPE= 99;
  12. namespace __private
  13. {
  14. function findlib()
  15. {
  16. for (string lib in [
  17. 'libmysqlclient',
  18. 'libmysqlclient.so.16',
  19. 'libmysqlclient.so.15'
  20. ] ) {
  21. var l = loadlib(lib);
  22. if (l)
  23. return l;
  24. }
  25. return null;
  26. }
  27. function getlib()
  28. {
  29. var l = findlib();
  30. if (! l)
  31. throw Error('Cannot load Mysql lib', ERROR, TYPE);
  32. for (;;)
  33. yield l;
  34. }
  35. function str_to_cstring(string s)
  36. {
  37. var cstring = new ['ByteBuffer'];
  38. cstring =: s;
  39. push(cstring, 0);
  40. return cstring;
  41. }
  42. } // namespace __private;
  43. using namespace __private;
  44. class Row
  45. {
  46. var mrow;
  47. var desc;
  48. var nfields;
  49. var encoding;
  50. function Row(var myrow, var desc, int n, string encoding[optional])
  51. {
  52. self.mrow = myrow;
  53. self.desc = desc;
  54. self.nfields = n;
  55. if (encoding != null)
  56. self.encoding = encoding;
  57. }
  58. function get(int i)
  59. {
  60. string encoding;
  61. if (self.encoding != null)
  62. encoding = self.encoding;
  63. var p = self.desc[self.mrow, i];
  64. string result;
  65. if (p != null) {
  66. result = p.as_string(encoding);
  67. }
  68. else
  69. result = '';
  70. return result;
  71. }
  72. }
  73. class Result
  74. {
  75. var mysql;
  76. var myresult;
  77. var nfields;
  78. var desc;
  79. function Result(var my, var r)
  80. {
  81. using WinxedMysql.getlib;
  82. self.mysql = my;
  83. self.myresult = r;
  84. var f = dlfunc(getlib(), 'mysql_field_count', 'ip');
  85. int count = f(my.mysql);
  86. self.nfields = count;
  87. int viewtype[count + 2] = [ DATATYPE_STRUCT, count ];
  88. for (int i = 2; i < count + 2; ++i)
  89. viewtype[i] = DATATYPE_PTR;
  90. var desc = new ['StructView'] (viewtype);
  91. self.desc = desc;
  92. }
  93. function field_count()
  94. {
  95. return self.nfields;
  96. }
  97. function fetch_row()
  98. {
  99. using WinxedMysql.getlib;
  100. var f = dlfunc(getlib(), 'mysql_fetch_row', 'pp');
  101. var frow = f(self.myresult);
  102. if (frow == null)
  103. return null;
  104. var none = new 'UnManagedStruct';
  105. if (frow == none)
  106. return null;
  107. string encoding;
  108. if (self.mysql.encoding != null)
  109. encoding = self.mysql.encoding;
  110. return new WinxedMysql.Row(frow, self.desc, self.nfields, encoding);
  111. }
  112. function close()
  113. {
  114. if (self.myresult != null)
  115. {
  116. using WinxedMysql.getlib;
  117. var f = dlfunc(getlib(), 'mysql_free_result', 'vp');
  118. f(self.myresult);
  119. self.myresult = null;
  120. }
  121. }
  122. }
  123. class Connection
  124. {
  125. var mysql;
  126. var encoding;
  127. function Connection()
  128. {
  129. using WinxedMysql.getlib;
  130. var minit = dlfunc(getlib(), 'mysql_init', 'pp');
  131. string nothing;
  132. var my = minit(null);
  133. self.mysql = my;
  134. }
  135. function close()
  136. {
  137. using WinxedMysql.getlib;
  138. var mclose = dlfunc(getlib(), 'mysql_close', 'vp');
  139. mclose(self.mysql);
  140. var n = new 'Undef';
  141. self.mysql = n;
  142. }
  143. function get_client_info()
  144. {
  145. using WinxedMysql.getlib;
  146. var f = dlfunc(getlib(), 'mysql_get_client_info', 'p');
  147. return f().as_string('utf8');
  148. }
  149. function error()
  150. {
  151. using WinxedMysql.getlib;
  152. var f = dlfunc(getlib(), 'mysql_error', 'pp');
  153. return f(self.mysql).as_string('utf8');
  154. }
  155. function connect(string host, string user, string pass, string database,
  156. string encoding)
  157. {
  158. using WinxedMysql.getlib;
  159. var f = dlfunc(getlib(), 'mysql_real_connect', 'ppppppipi');
  160. string snull;
  161. var phost = str_to_cstring(host);
  162. var puser = str_to_cstring(user);
  163. var ppass = str_to_cstring(pass);
  164. var pdatabase = str_to_cstring(database);
  165. var p = f(self.mysql, phost, puser, ppass, pdatabase, 0, null, 0);
  166. if (p == null)
  167. throw Error(self.error(), ERROR, TYPE);
  168. var none = new 'UnManagedStruct';
  169. if (p == none)
  170. throw Error(self.error(), ERROR, TYPE);
  171. var setcharset = dlfunc(getlib(), 'mysql_set_character_set', 'ipp');
  172. if (encoding != null) {
  173. int i = setcharset(self.mysql, str_to_cstring(encoding));
  174. if (i != 0)
  175. cry('Failed to set character set.');
  176. self.encoding = encoding;
  177. }
  178. return p;
  179. }
  180. function query(string stmt)
  181. {
  182. using WinxedMysql.getlib;
  183. var f = dlfunc(getlib(), 'mysql_query', 'ipp');
  184. var pstmt = str_to_cstring(stmt);
  185. int q = f(self.mysql, pstmt);
  186. if (q != 0)
  187. throw Error(self.error(), ERROR, TYPE);
  188. }
  189. function use_result()
  190. {
  191. using WinxedMysql.getlib;
  192. var f = dlfunc(getlib(), 'mysql_use_result', 'pp');
  193. var r = f(self.mysql);
  194. if (r == null)
  195. throw Error(self.error(), ERROR, TYPE);
  196. var none = new 'UnManagedStruct';
  197. if (r == none)
  198. throw Error(self.error(), ERROR, TYPE);
  199. return new WinxedMysql.Result(self, r);
  200. }
  201. }
  202. } // namespace WinxedMysql
  203. $load 'Getopt/Obj.pbc';
  204. function main(argv)
  205. {
  206. using namespace WinxedMysql;
  207. var getopts = new ['Getopt', 'Obj'];
  208. getopts.notOptStop(1);
  209. getopts.push_string('host|h=s');
  210. getopts.push_string('user|u=s');
  211. getopts.push_string('password|p:s');
  212. getopts.push_string('database|D=s');
  213. getopts.push_string('encoding|D=s');
  214. getopts.push_string('config|D=s');
  215. argv.shift();
  216. var opts = getopts.get_options(argv);
  217. string host;
  218. string user;
  219. string pass;
  220. string database;
  221. string encoding;
  222. string config = opts['config'];
  223. if (config != null && config != '') {
  224. // Get config from file in json format.
  225. try {
  226. var json = load_language('data_json');
  227. var code = json.compile(open(config).readall());
  228. var data = code();
  229. if (data['host'] != null)
  230. host = data['host'];
  231. if (data['user'] != null)
  232. user = data['user'];
  233. if (data['password'] != null)
  234. pass = data['password'];
  235. if (data['database'] != null)
  236. database = data['database'];
  237. if (data['encoding'] != null)
  238. encoding = data['encoding'];
  239. }
  240. catch (e) {
  241. cry('Error reading config file: ', e['message']);
  242. return;
  243. }
  244. }
  245. if (opts['host'] != null)
  246. host = opts['host'];
  247. if (opts['user'] != null)
  248. user = opts['user'];
  249. if (opts['password'] != null)
  250. pass= opts['password'];
  251. if (opts['database'] != null)
  252. database = opts['database'];
  253. if (opts['encoding'] != null)
  254. encoding = opts['encoding'];
  255. if (encoding != null) {
  256. // Get the encoding number and get back the name from it.
  257. // This simplifies the usage of encoding aliases and
  258. // catch not available or invalid encodings.
  259. int encnum;
  260. try {
  261. ${ find_encoding encnum, encoding };
  262. ${ encodingname encoding, encnum };
  263. }
  264. catch() {
  265. cry("Encoding '" + encoding + "' not available");
  266. exit(1);
  267. }
  268. }
  269. if (host == null || host == '')
  270. host = 'localhost';
  271. if (user == null || user == '')
  272. user = 'parrot';
  273. if (pass == null)
  274. pass = 'baDworD';
  275. else if (pass == '')
  276. die("Sorry, asking for password not implemented");
  277. if (database == null || database == '')
  278. database = 'parrot';
  279. var mysql = new WinxedMysql.Connection();
  280. say('Mysql version: ', mysql.get_client_info());
  281. var result;
  282. try [min_severity(ERROR),max_severity(ERROR),handle_types(TYPE)] {
  283. mysql.connect(host, user, pass, database, encoding);
  284. string q = 'select * from hello;';
  285. if (elements(argv) > 0) {
  286. q = string(argv.shift());
  287. }
  288. for(;;) {
  289. say("Query: '", q, "'");
  290. mysql.query(q);
  291. result = mysql.use_result();
  292. int fields = result.field_count();
  293. int nrows = 0;
  294. var row;
  295. while ((row = result.fetch_row()) != null) {
  296. ++nrows;
  297. print(nrows, ': ');
  298. for (int i = 0; i < fields; ++i) {
  299. if (i > 0)
  300. print(", ");
  301. string s = row.get(i);
  302. if (s == null)
  303. print('(null)');
  304. else
  305. print("'", s, "'");
  306. }
  307. say();
  308. }
  309. result.close();
  310. say('Total rows: ', nrows);
  311. if (elements(argv) == 0)
  312. break;
  313. q = string(argv.shift());
  314. }
  315. }
  316. catch (e) {
  317. say("\tERROR: ", e['message']);
  318. if (result != null)
  319. result.close();
  320. mysql.close();
  321. return;
  322. }
  323. mysql.close();
  324. }
  325. // End