PageRenderTime 41ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/db-mysql/mysql-api.lisp

https://github.com/thijs/clsql-fork
Lisp | 519 lines | 402 code | 82 blank | 35 comment | 0 complexity | ca126add0f1f1931f1fba3338638c3ad MD5 | raw file
Possible License(s): LGPL-3.0, CC-BY-SA-3.0
  1. ;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
  2. ;;;; *************************************************************************
  3. ;;;; FILE IDENTIFICATION
  4. ;;;;
  5. ;;;; Name: mysql-api.lisp
  6. ;;;; Purpose: Low-level MySQL interface using UFFI
  7. ;;;; Programmers: Kevin M. Rosenberg based on
  8. ;;;; Original code by Pierre R. Mai
  9. ;;;; Date Started: Feb 2002
  10. ;;;;
  11. ;;;; This file, part of CLSQL, is Copyright (c) 2002-2009 by Kevin M. Rosenberg
  12. ;;;; and Copyright (c) 1999-2001 by Pierre R. Mai
  13. ;;;;
  14. ;;;; CLSQL users are granted the rights to distribute and use this software
  15. ;;;; as governed by the terms of the Lisp Lesser GNU Public License
  16. ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
  17. ;;;; *************************************************************************
  18. (in-package #:mysql)
  19. ;;;; Modifications from original code
  20. ;;;; - Updated C-structures to conform to structures in MySQL 3.23.46
  21. ;;;; - Changed from CMUCL interface to UFFI
  22. ;;;; - Added and call a C-helper file to support 64-bit integers
  23. ;;;; that are used in a few routines.
  24. ;;;; - Removed all references to interiors of C-structions, this will
  25. ;;;; increase robustness when MySQL's internal structures change.
  26. ;;;; Type definitions
  27. ;;; Basic Types
  28. (uffi:def-foreign-type mysql-socket :int)
  29. (uffi:def-foreign-type mysql-bool :byte)
  30. (uffi:def-foreign-type mysql-byte :unsigned-char)
  31. (uffi:def-enum mysql-net-type
  32. (:tcp-ip
  33. :socket
  34. :named-pipe))
  35. (uffi:def-array-pointer mysql-row (* :unsigned-char))
  36. ;;; MYSQL-FIELD
  37. (uffi:def-enum mysql-field-types
  38. (:decimal
  39. :tiny
  40. :short
  41. :long
  42. :float
  43. :double
  44. :null
  45. :timestamp
  46. :longlong
  47. :int24
  48. :date
  49. :time
  50. :datetime
  51. :year
  52. :newdate
  53. (:enum 247)
  54. (:set 248)
  55. (:tiny-blob 249)
  56. (:medium-blob 250)
  57. (:long-blob 251)
  58. (:blob 252)
  59. (:var-string 253)
  60. (:string 254)
  61. (:geometry 255)))
  62. (uffi:def-enum mysql-option
  63. (:connect-timeout
  64. :compress
  65. :named-pipe
  66. :init-command
  67. :read-default-file
  68. :read-default-group))
  69. (uffi:def-enum mysql-status
  70. (:ready
  71. :get-result
  72. :use-result))
  73. #+(or mysql-client-v4.1 mysql-client-v5)
  74. (uffi:def-enum mysql-field-types
  75. (:ready
  76. :get-result
  77. :use-result))
  78. ;;; Opaque pointers to mysql C-defined structures
  79. (uffi:def-foreign-type mysql-mysql (* :void))
  80. (uffi:def-foreign-type mysql-mysql-res (* :void))
  81. (uffi:def-foreign-type mysql-field (* :void))
  82. (uffi:def-foreign-type mysql-bind (* :void))
  83. ;;;; The Foreign C routines
  84. (declaim (inline mysql-init))
  85. (uffi:def-function "mysql_init"
  86. ((mysql mysql-mysql))
  87. :module "mysql"
  88. :returning mysql-mysql)
  89. ;; Need to comment this out for LW 4.2.6
  90. ;; ? bug in LW version
  91. #-lispworks (declaim (inline mysql-real-connect))
  92. (uffi:def-function "mysql_real_connect"
  93. ((mysql mysql-mysql)
  94. (host :cstring)
  95. (user :cstring)
  96. (passwd :cstring)
  97. (db :cstring)
  98. (port :unsigned-int)
  99. (unix-socket :cstring)
  100. (clientflag :unsigned-long))
  101. :module "mysql"
  102. :returning mysql-mysql)
  103. (declaim (inline mysql-close))
  104. (uffi:def-function "mysql_close"
  105. ((sock mysql-mysql))
  106. :module "mysql"
  107. :returning :void)
  108. (declaim (inline mysql-select-db))
  109. (uffi:def-function "mysql_select_db"
  110. ((mysql mysql-mysql)
  111. (db :cstring))
  112. :module "mysql"
  113. :returning :int)
  114. (declaim (inline mysql-query))
  115. (uffi:def-function "mysql_query"
  116. ((mysql mysql-mysql)
  117. (query :cstring))
  118. :module "mysql"
  119. :returning :int)
  120. ;;; I doubt that this function is really useful for direct Lisp usage,
  121. ;;; but it is here for completeness...
  122. (declaim (inline mysql-real-query))
  123. (uffi:def-function "mysql_real_query"
  124. ((mysql mysql-mysql)
  125. (query :cstring)
  126. (length :unsigned-int))
  127. :module "mysql"
  128. :returning :int)
  129. (declaim (inline mysql-shutdown))
  130. (uffi:def-function "mysql_shutdown"
  131. ((mysql mysql-mysql))
  132. :module "mysql"
  133. :returning :int)
  134. (declaim (inline mysql-dump-debug-info))
  135. (uffi:def-function "mysql_dump_debug_info"
  136. ((mysql mysql-mysql))
  137. :module "mysql"
  138. :returning :int)
  139. (declaim (inline mysql-refresh))
  140. (uffi:def-function "mysql_refresh"
  141. ((mysql mysql-mysql)
  142. (refresh-options :unsigned-int))
  143. :module "mysql"
  144. :returning :int)
  145. (declaim (inline mysql-kill))
  146. (uffi:def-function "mysql_kill"
  147. ((mysql mysql-mysql)
  148. (pid :unsigned-long))
  149. :module "mysql"
  150. :returning :int)
  151. (declaim (inline mysql-ping))
  152. (uffi:def-function "mysql_ping"
  153. ((mysql mysql-mysql))
  154. :module "mysql"
  155. :returning :int)
  156. (declaim (inline mysql-stat))
  157. (uffi:def-function "mysql_stat"
  158. ((mysql mysql-mysql))
  159. :module "mysql"
  160. :returning :cstring)
  161. (declaim (inline mysql-get-server-info))
  162. (uffi:def-function "mysql_get_server_info"
  163. ((mysql mysql-mysql))
  164. :module "mysql"
  165. :returning :cstring)
  166. (declaim (inline mysql-get-host-info))
  167. (uffi:def-function "mysql_get_host_info"
  168. ((mysql mysql-mysql))
  169. :module "mysql"
  170. :returning :cstring)
  171. (declaim (inline mysql-get-proto-info))
  172. (uffi:def-function "mysql_get_proto_info"
  173. ((mysql mysql-mysql))
  174. :module "mysql"
  175. :returning :unsigned-int)
  176. (declaim (inline mysql-list-dbs))
  177. (uffi:def-function "mysql_list_dbs"
  178. ((mysql mysql-mysql)
  179. (wild :cstring))
  180. :module "mysql"
  181. :returning mysql-mysql-res)
  182. (declaim (inline mysql-list-tables))
  183. (uffi:def-function "mysql_list_tables"
  184. ((mysql mysql-mysql)
  185. (wild :cstring))
  186. :module "mysql"
  187. :returning mysql-mysql-res)
  188. (declaim (inline mysql-list-fields))
  189. (uffi:def-function "mysql_list_fields"
  190. ((mysql mysql-mysql)
  191. (table :cstring)
  192. (wild :cstring))
  193. :module "mysql"
  194. :returning mysql-mysql-res)
  195. (declaim (inline mysql-list-processes))
  196. (uffi:def-function "mysql_list_processes"
  197. ((mysql mysql-mysql))
  198. :module "mysql"
  199. :returning mysql-mysql-res)
  200. (declaim (inline mysql-store-result))
  201. (uffi:def-function "mysql_store_result"
  202. ((mysql mysql-mysql))
  203. :module "mysql"
  204. :returning mysql-mysql-res)
  205. (declaim (inline mysql-use-result))
  206. (uffi:def-function "mysql_use_result"
  207. ((mysql mysql-mysql))
  208. :module "mysql"
  209. :returning mysql-mysql-res)
  210. (declaim (inline mysql-options))
  211. (uffi:def-function "mysql_options"
  212. ((mysql mysql-mysql)
  213. (option mysql-option)
  214. (arg :cstring))
  215. :module "mysql"
  216. :returning :int)
  217. (declaim (inline mysql-free-result))
  218. (uffi:def-function "mysql_free_result"
  219. ((res mysql-mysql-res))
  220. :module "mysql"
  221. :returning :void)
  222. (declaim (inline mysql-fetch-row))
  223. (uffi:def-function "mysql_fetch_row"
  224. ((res mysql-mysql-res))
  225. :module "mysql"
  226. :returning (* (* :unsigned-char)))
  227. (declaim (inline mysql-fetch-lengths))
  228. (uffi:def-function "mysql_fetch_lengths"
  229. ((res mysql-mysql-res))
  230. :module "mysql"
  231. :returning (* :unsigned-long))
  232. (declaim (inline mysql-fetch-field))
  233. (uffi:def-function "mysql_fetch_field"
  234. ((res mysql-mysql-res))
  235. :module "mysql"
  236. :returning mysql-field)
  237. (declaim (inline mysql-field-seek))
  238. (uffi:def-function "mysql_field_seek"
  239. ((res mysql-mysql-res)
  240. (offset :unsigned-int))
  241. :module "mysql"
  242. :returning :unsigned-int)
  243. (declaim (inline mysql-fetch-fields))
  244. (uffi:def-function "mysql_fetch_fields"
  245. ((res mysql-mysql-res))
  246. :module "mysql"
  247. :returning mysql-field)
  248. (declaim (inline mysql-fetch-field-direct))
  249. (uffi:def-function "mysql_fetch_field_direct"
  250. ((res mysql-mysql-res)
  251. (field-num :unsigned-int))
  252. :module "mysql"
  253. :returning mysql-field)
  254. (declaim (inline mysql-escape-string))
  255. (uffi:def-function "mysql_escape_string"
  256. ((to (* :unsigned-char))
  257. (from (* :unsigned-char))
  258. (length :unsigned-int))
  259. :module "mysql"
  260. :returning :unsigned-int)
  261. (declaim (inline mysql-debug))
  262. (uffi:def-function "mysql_debug"
  263. ((debug :cstring))
  264. :module "mysql"
  265. :returning :void)
  266. (declaim (inline clsql-mysql-num-rows))
  267. (uffi:def-function "clsql_mysql_num_rows"
  268. ((res mysql-mysql-res)
  269. (p-high32 (* :unsigned-int)))
  270. :module "clsql-mysql"
  271. :returning :unsigned-int)
  272. #+(or mysql-client-v4.1 mysql-client-v5)
  273. (uffi:def-foreign-type mysql-stmt-ptr :pointer-void)
  274. #+(or mysql-client-v4.1 mysql-client-v5)
  275. (uffi:def-function "mysql_stmt_init"
  276. ((res mysql-mysql-res))
  277. :module "clsql-mysql"
  278. :returning mysql-stmt-ptr)
  279. #+(or mysql-client-v4.1 mysql-client-v5)
  280. (uffi:def-function "mysql_stmt_prepare"
  281. ((stmt mysql-stmt-ptr)
  282. (query :cstring)
  283. (length :unsigned-long))
  284. :module "clsql-mysql"
  285. :returning :int)
  286. #+(or mysql-client-v4.1 mysql-client-v5)
  287. (uffi:def-function "mysql_stmt_param_count"
  288. ((stmt mysql-stmt-ptr))
  289. :module "clsql-mysql"
  290. :returning :unsigned-int)
  291. #+(or mysql-client-v4.1 mysql-client-v5)
  292. (uffi:def-function "mysql_stmt_bind_param"
  293. ((stmt mysql-stmt-ptr)
  294. (bind mysql-bind))
  295. :module "clsql-mysql"
  296. :returning :short)
  297. #+(or mysql-client-v4.1 mysql-client-v5)
  298. (uffi:def-function "mysql_stmt_bind_result"
  299. ((stmt mysql-stmt-ptr)
  300. (bind mysql-bind))
  301. :module "clsql-mysql"
  302. :returning :short)
  303. #+(or mysql-client-v4.1 mysql-client-v5)
  304. (uffi:def-function "mysql_stmt_result_metadata"
  305. ((stmt mysql-stmt-ptr))
  306. :module "clsql-mysql"
  307. :returning mysql-mysql-res)
  308. #+(or mysql-client-v4.1 mysql-client-v5)
  309. (uffi:def-function "mysql_stmt_execute"
  310. ((stmt mysql-stmt-ptr))
  311. :module "clsql-mysql"
  312. :returning :int)
  313. #+(or mysql-client-v4.1 mysql-client-v5)
  314. (uffi:def-function "mysql_stmt_store_result"
  315. ((stmt mysql-stmt-ptr))
  316. :module "clsql-mysql"
  317. :returning :int)
  318. #+(or mysql-client-v4.1 mysql-client-v5)
  319. (uffi:def-function "mysql_stmt_fetch"
  320. ((stmt mysql-stmt-ptr))
  321. :module "clsql-mysql"
  322. :returning :int)
  323. #+(or mysql-client-v4.1 mysql-client-v5)
  324. (uffi:def-function "mysql_stmt_free_result"
  325. ((stmt mysql-stmt-ptr))
  326. :module "clsql-mysql"
  327. :returning :short)
  328. #+(or mysql-client-v4.1 mysql-client-v5)
  329. (uffi:def-function "mysql_stmt_close"
  330. ((stmt mysql-stmt-ptr))
  331. :module "clsql-mysql"
  332. :returning :short)
  333. #+(or mysql-client-v4.1 mysql-client-v5)
  334. (uffi:def-function "mysql_stmt_errno"
  335. ((stmt mysql-stmt-ptr))
  336. :module "clsql-mysql"
  337. :returning :unsigned-int)
  338. #+(or mysql-client-v4.1 mysql-client-v5)
  339. (uffi:def-function "mysql_stmt_error"
  340. ((stmt mysql-stmt-ptr))
  341. :module "clsql-mysql"
  342. :returning :cstring)
  343. ;;;; Equivalents of C Macro definitions for accessing various fields
  344. ;;;; in the internal MySQL Datastructures
  345. (declaim (inline mysql-num-rows))
  346. (defun mysql-num-rows (res)
  347. (uffi:with-foreign-object (p-high32 :unsigned-int)
  348. (let ((low32 (clsql-mysql-num-rows res p-high32))
  349. (high32 (uffi:deref-pointer p-high32 :unsigned-int)))
  350. (if (zerop high32)
  351. low32
  352. (make-64-bit-integer high32 low32)))))
  353. (uffi:def-function "clsql_mysql_affected_rows"
  354. ((mysql mysql-mysql)
  355. (p-high32 (* :unsigned-int)))
  356. :returning :unsigned-int
  357. :module "clsql-mysql")
  358. (defun mysql-affected-rows (mysql)
  359. (uffi:with-foreign-object (p-high32 :unsigned-int)
  360. (let ((low32 (clsql-mysql-affected-rows mysql p-high32))
  361. (high32 (uffi:deref-pointer p-high32 :unsigned-int)))
  362. (if (zerop high32)
  363. low32
  364. (make-64-bit-integer high32 low32)))))
  365. (uffi:def-function "clsql_mysql_insert_id"
  366. ((res mysql-mysql)
  367. (p-high32 (* :unsigned-int)))
  368. :returning :unsigned-int
  369. :module "clsql-mysql")
  370. (defun mysql-insert-id (mysql)
  371. (uffi:with-foreign-object (p-high32 :unsigned-int)
  372. (let ((low32 (clsql-mysql-insert-id mysql p-high32))
  373. (high32 (uffi:deref-pointer p-high32 :unsigned-int)))
  374. (if (zerop high32)
  375. low32
  376. (make-64-bit-integer high32 low32)))))
  377. (declaim (inline mysql-num-fields))
  378. (uffi:def-function "mysql_num_fields"
  379. ((res mysql-mysql-res))
  380. :returning :unsigned-int
  381. :module "mysql")
  382. (declaim (inline clsql-mysql-eof))
  383. (uffi:def-function ("mysql_eof" clsql-mysql-eof)
  384. ((res mysql-mysql-res))
  385. :returning :char
  386. :module "mysql")
  387. (declaim (inline mysql-eof))
  388. (defun mysql-eof (res)
  389. (if (zerop (clsql-mysql-eof res))
  390. nil
  391. t))
  392. (declaim (inline mysql-error))
  393. (uffi:def-function ("mysql_error" mysql-error)
  394. ((mysql mysql-mysql))
  395. :returning :cstring
  396. :module "mysql")
  397. (declaim (inline mysql-error-string))
  398. (defun mysql-error-string (mysql)
  399. (uffi:convert-from-cstring (mysql-error mysql)))
  400. (declaim (inline mysql-errno))
  401. (uffi:def-function "mysql_errno"
  402. ((mysql mysql-mysql))
  403. :returning :unsigned-int
  404. :module "mysql")
  405. (declaim (inline mysql-info))
  406. (uffi:def-function ("mysql_info" mysql-info)
  407. ((mysql mysql-mysql))
  408. :returning :cstring
  409. :module "mysql")
  410. (declaim (inline mysql-info-string))
  411. (defun mysql-info-string (mysql)
  412. (uffi:convert-from-cstring (mysql-info mysql)))
  413. (declaim (inline clsql-mysql-data-seek))
  414. (uffi:def-function "clsql_mysql_data_seek"
  415. ((res mysql-mysql-res)
  416. (offset-high32 :unsigned-int)
  417. (offset-low32 :unsigned-int))
  418. :module "clsql-mysql"
  419. :returning :void)
  420. (declaim (inline clsql-mysql-field-name))
  421. (uffi:def-function "clsql_mysql_field_name"
  422. ((res mysql-field))
  423. :module "clsql-mysql"
  424. :returning :cstring)
  425. (declaim (inline clsql-mysql-field-flags))
  426. (uffi:def-function "clsql_mysql_field_flags"
  427. ((res mysql-field))
  428. :module "clsql-mysql"
  429. :returning :unsigned-int)
  430. (declaim (inline clsql-mysql-field-type))
  431. (uffi:def-function "clsql_mysql_field_type"
  432. ((res mysql-field))
  433. :module "clsql-mysql"
  434. :returning :unsigned-int)
  435. (defun mysql-data-seek (res offset)
  436. (multiple-value-bind (high32 low32) (split-64-bit-integer offset)
  437. (clsql-mysql-data-seek res high32 low32)))