Use :verbose nil for asdf:operate invocation
[clsql/s11.git] / db-mysql / mysql-api.lisp
blob91fc3c5a6998807f31520f94bee61b0f7a2b8aea
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 ;;;; *************************************************************************
19 (in-package #:mysql)
21 ;;;; Modifications from original code
22 ;;;; - Updated C-structures to conform to structures in MySQL 3.23.46
23 ;;;; - Changed from CMUCL interface to UFFI
24 ;;;; - Added and call a C-helper file to support 64-bit integers
25 ;;;; that are used in a few routines.
26 ;;;; - Removed all references to interiors of C-structions, this will
27 ;;;; increase robustness when MySQL's internal structures change.
29 ;;;; Type definitions
31 ;;; Basic Types
33 (uffi:def-foreign-type mysql-socket :int)
34 (uffi:def-foreign-type mysql-bool :byte)
35 (uffi:def-foreign-type mysql-byte :unsigned-char)
37 (uffi:def-enum mysql-net-type
38 (:tcp-ip
39 :socket
40 :named-pipe))
42 (uffi:def-array-pointer mysql-row (* :unsigned-char))
44 ;;; MYSQL-FIELD
45 (uffi:def-enum mysql-field-types
46 (:decimal
47 :tiny
48 :short
49 :long
50 :float
51 :double
52 :null
53 :timestamp
54 :longlong
55 :int24
56 :date
57 :time
58 :datetime
59 :year
60 :newdate
61 (:enum 247)
62 (:set 248)
63 (:tiny-blob 249)
64 (:medium-blob 250)
65 (:long-blob 251)
66 (:blob 252)
67 (:var-string 253)
68 (:string 254)
69 (:geometry 255)))
71 (uffi:def-enum mysql-option
72 (:connect-timeout
73 :compress
74 :named-pipe
75 :init-command
76 :read-default-file
77 :read-default-group))
79 (uffi:def-enum mysql-status
80 (:ready
81 :get-result
82 :use-result))
84 #+(or mysql-client-v4.1 mysql-client-v5)
85 (uffi:def-enum mysql-field-types
86 (:ready
87 :get-result
88 :use-result))
90 ;;; Opaque pointers to mysql C-defined structures
91 (uffi:def-foreign-type mysql-mysql (* :void))
92 (uffi:def-foreign-type mysql-mysql-res (* :void))
93 (uffi:def-foreign-type mysql-field (* :void))
94 (uffi:def-foreign-type mysql-bind (* :void))
96 ;;;; The Foreign C routines
97 (declaim (inline mysql-init))
98 (uffi:def-function "mysql_init"
99 ((mysql mysql-mysql))
100 :module "mysql"
101 :returning mysql-mysql)
103 ;; Need to comment this out for LW 4.2.6
104 ;; ? bug in LW version
105 #-lispworks (declaim (inline mysql-real-connect))
106 (uffi:def-function "mysql_real_connect"
107 ((mysql mysql-mysql)
108 (host :cstring)
109 (user :cstring)
110 (passwd :cstring)
111 (db :cstring)
112 (port :unsigned-int)
113 (unix-socket :cstring)
114 (clientflag :unsigned-long))
115 :module "mysql"
116 :returning mysql-mysql)
118 (declaim (inline mysql-close))
119 (uffi:def-function "mysql_close"
120 ((sock mysql-mysql))
121 :module "mysql"
122 :returning :void)
124 (declaim (inline mysql-select-db))
125 (uffi:def-function "mysql_select_db"
126 ((mysql mysql-mysql)
127 (db :cstring))
128 :module "mysql"
129 :returning :int)
131 (declaim (inline mysql-query))
132 (uffi:def-function "mysql_query"
133 ((mysql mysql-mysql)
134 (query :cstring))
135 :module "mysql"
136 :returning :int)
138 ;;; I doubt that this function is really useful for direct Lisp usage,
139 ;;; but it is here for completeness...
141 (declaim (inline mysql-real-query))
142 (uffi:def-function "mysql_real_query"
143 ((mysql mysql-mysql)
144 (query :cstring)
145 (length :unsigned-int))
146 :module "mysql"
147 :returning :int)
149 (declaim (inline mysql-shutdown))
150 (uffi:def-function "mysql_shutdown"
151 ((mysql mysql-mysql))
152 :module "mysql"
153 :returning :int)
155 (declaim (inline mysql-dump-debug-info))
156 (uffi:def-function "mysql_dump_debug_info"
157 ((mysql mysql-mysql))
158 :module "mysql"
159 :returning :int)
161 (declaim (inline mysql-refresh))
162 (uffi:def-function "mysql_refresh"
163 ((mysql mysql-mysql)
164 (refresh-options :unsigned-int))
165 :module "mysql"
166 :returning :int)
168 (declaim (inline mysql-kill))
169 (uffi:def-function "mysql_kill"
170 ((mysql mysql-mysql)
171 (pid :unsigned-long))
172 :module "mysql"
173 :returning :int)
175 (declaim (inline mysql-ping))
176 (uffi:def-function "mysql_ping"
177 ((mysql mysql-mysql))
178 :module "mysql"
179 :returning :int)
181 (declaim (inline mysql-stat))
182 (uffi:def-function "mysql_stat"
183 ((mysql mysql-mysql))
184 :module "mysql"
185 :returning :cstring)
187 (declaim (inline mysql-get-server-info))
188 (uffi:def-function "mysql_get_server_info"
189 ((mysql mysql-mysql))
190 :module "mysql"
191 :returning :cstring)
193 (declaim (inline mysql-get-host-info))
194 (uffi:def-function "mysql_get_host_info"
195 ((mysql mysql-mysql))
196 :module "mysql"
197 :returning :cstring)
199 (declaim (inline mysql-get-proto-info))
200 (uffi:def-function "mysql_get_proto_info"
201 ((mysql mysql-mysql))
202 :module "mysql"
203 :returning :unsigned-int)
205 (declaim (inline mysql-list-dbs))
206 (uffi:def-function "mysql_list_dbs"
207 ((mysql mysql-mysql)
208 (wild :cstring))
209 :module "mysql"
210 :returning mysql-mysql-res)
212 (declaim (inline mysql-list-tables))
213 (uffi:def-function "mysql_list_tables"
214 ((mysql mysql-mysql)
215 (wild :cstring))
216 :module "mysql"
217 :returning mysql-mysql-res)
219 (declaim (inline mysql-list-fields))
220 (uffi:def-function "mysql_list_fields"
221 ((mysql mysql-mysql)
222 (table :cstring)
223 (wild :cstring))
224 :module "mysql"
225 :returning mysql-mysql-res)
227 (declaim (inline mysql-list-processes))
228 (uffi:def-function "mysql_list_processes"
229 ((mysql mysql-mysql))
230 :module "mysql"
231 :returning mysql-mysql-res)
233 (declaim (inline mysql-store-result))
234 (uffi:def-function "mysql_store_result"
235 ((mysql mysql-mysql))
236 :module "mysql"
237 :returning mysql-mysql-res)
239 (declaim (inline mysql-use-result))
240 (uffi:def-function "mysql_use_result"
241 ((mysql mysql-mysql))
242 :module "mysql"
243 :returning mysql-mysql-res)
245 (declaim (inline mysql-options))
246 (uffi:def-function "mysql_options"
247 ((mysql mysql-mysql)
248 (option mysql-option)
249 (arg :cstring))
250 :module "mysql"
251 :returning :int)
253 (declaim (inline mysql-free-result))
254 (uffi:def-function "mysql_free_result"
255 ((res mysql-mysql-res))
256 :module "mysql"
257 :returning :void)
259 (declaim (inline mysql-fetch-row))
260 (uffi:def-function "mysql_fetch_row"
261 ((res mysql-mysql-res))
262 :module "mysql"
263 :returning (* (* :unsigned-char)))
265 (declaim (inline mysql-fetch-lengths))
266 (uffi:def-function "mysql_fetch_lengths"
267 ((res mysql-mysql-res))
268 :module "mysql"
269 :returning (* :unsigned-long))
271 (declaim (inline mysql-fetch-field))
272 (uffi:def-function "mysql_fetch_field"
273 ((res mysql-mysql-res))
274 :module "mysql"
275 :returning mysql-field)
277 (declaim (inline mysql-field-seek))
278 (uffi:def-function "mysql_field_seek"
279 ((res mysql-mysql-res)
280 (offset :unsigned-int))
281 :module "mysql"
282 :returning :unsigned-int)
284 (declaim (inline mysql-fetch-fields))
285 (uffi:def-function "mysql_fetch_fields"
286 ((res mysql-mysql-res))
287 :module "mysql"
288 :returning mysql-field)
290 (declaim (inline mysql-fetch-field-direct))
291 (uffi:def-function "mysql_fetch_field_direct"
292 ((res mysql-mysql-res)
293 (field-num :unsigned-int))
294 :module "mysql"
295 :returning mysql-field)
297 (declaim (inline mysql-escape-string))
298 (uffi:def-function "mysql_escape_string"
299 ((to (* :unsigned-char))
300 (from (* :unsigned-char))
301 (length :unsigned-int))
302 :module "mysql"
303 :returning :unsigned-int)
305 (declaim (inline mysql-debug))
306 (uffi:def-function "mysql_debug"
307 ((debug :cstring))
308 :module "mysql"
309 :returning :void)
311 (declaim (inline clsql-mysql-num-rows))
312 (uffi:def-function "clsql_mysql_num_rows"
313 ((res mysql-mysql-res)
314 (p-high32 (* :unsigned-int)))
315 :module "clsql-mysql"
316 :returning :unsigned-int)
318 #+(or mysql-client-v4.1 mysql-client-v5)
319 (uffi:def-foreign-type mysql-stmt-ptr :pointer-void)
321 #+(or mysql-client-v4.1 mysql-client-v5)
322 (uffi:def-function "mysql_stmt_init"
323 ((res mysql-mysql-res))
324 :module "clsql-mysql"
325 :returning mysql-stmt-ptr)
327 #+(or mysql-client-v4.1 mysql-client-v5)
328 (uffi:def-function "mysql_stmt_prepare"
329 ((stmt mysql-stmt-ptr)
330 (query :cstring)
331 (length :unsigned-long))
332 :module "clsql-mysql"
333 :returning :int)
335 #+(or mysql-client-v4.1 mysql-client-v5)
336 (uffi:def-function "mysql_stmt_param_count"
337 ((stmt mysql-stmt-ptr))
338 :module "clsql-mysql"
339 :returning :unsigned-int)
341 #+(or mysql-client-v4.1 mysql-client-v5)
342 (uffi:def-function "mysql_stmt_bind_param"
343 ((stmt mysql-stmt-ptr)
344 (bind mysql-bind))
345 :module "clsql-mysql"
346 :returning :short)
348 #+(or mysql-client-v4.1 mysql-client-v5)
349 (uffi:def-function "mysql_stmt_bind_result"
350 ((stmt mysql-stmt-ptr)
351 (bind mysql-bind))
352 :module "clsql-mysql"
353 :returning :short)
355 #+(or mysql-client-v4.1 mysql-client-v5)
356 (uffi:def-function "mysql_stmt_result_metadata"
357 ((stmt mysql-stmt-ptr))
358 :module "clsql-mysql"
359 :returning mysql-mysql-res)
362 #+(or mysql-client-v4.1 mysql-client-v5)
363 (uffi:def-function "mysql_stmt_execute"
364 ((stmt mysql-stmt-ptr))
365 :module "clsql-mysql"
366 :returning :int)
368 #+(or mysql-client-v4.1 mysql-client-v5)
369 (uffi:def-function "mysql_stmt_store_result"
370 ((stmt mysql-stmt-ptr))
371 :module "clsql-mysql"
372 :returning :int)
374 #+(or mysql-client-v4.1 mysql-client-v5)
375 (uffi:def-function "mysql_stmt_fetch"
376 ((stmt mysql-stmt-ptr))
377 :module "clsql-mysql"
378 :returning :int)
380 #+(or mysql-client-v4.1 mysql-client-v5)
381 (uffi:def-function "mysql_stmt_free_result"
382 ((stmt mysql-stmt-ptr))
383 :module "clsql-mysql"
384 :returning :short)
386 #+(or mysql-client-v4.1 mysql-client-v5)
387 (uffi:def-function "mysql_stmt_close"
388 ((stmt mysql-stmt-ptr))
389 :module "clsql-mysql"
390 :returning :short)
392 #+(or mysql-client-v4.1 mysql-client-v5)
393 (uffi:def-function "mysql_stmt_errno"
394 ((stmt mysql-stmt-ptr))
395 :module "clsql-mysql"
396 :returning :unsigned-int)
398 #+(or mysql-client-v4.1 mysql-client-v5)
399 (uffi:def-function "mysql_stmt_error"
400 ((stmt mysql-stmt-ptr))
401 :module "clsql-mysql"
402 :returning :cstring)
405 ;;;; Equivalents of C Macro definitions for accessing various fields
406 ;;;; in the internal MySQL Datastructures
409 (declaim (inline mysql-num-rows))
410 (defun mysql-num-rows (res)
411 (uffi:with-foreign-object (p-high32 :unsigned-int)
412 (let ((low32 (clsql-mysql-num-rows res p-high32))
413 (high32 (uffi:deref-pointer p-high32 :unsigned-int)))
414 (if (zerop high32)
415 low32
416 (make-64-bit-integer high32 low32)))))
418 (uffi:def-function "clsql_mysql_affected_rows"
419 ((mysql mysql-mysql)
420 (p-high32 (* :unsigned-int)))
421 :returning :unsigned-int
422 :module "clsql-mysql")
424 (defun mysql-affected-rows (mysql)
425 (uffi:with-foreign-object (p-high32 :unsigned-int)
426 (let ((low32 (clsql-mysql-affected-rows mysql p-high32))
427 (high32 (uffi:deref-pointer p-high32 :unsigned-int)))
428 (if (zerop high32)
429 low32
430 (make-64-bit-integer high32 low32)))))
432 (uffi:def-function "clsql_mysql_insert_id"
433 ((res mysql-mysql)
434 (p-high32 (* :unsigned-int)))
435 :returning :unsigned-int
436 :module "clsql-mysql")
438 (defun mysql-insert-id (mysql)
439 (uffi:with-foreign-object (p-high32 :unsigned-int)
440 (let ((low32 (clsql-mysql-insert-id mysql p-high32))
441 (high32 (uffi:deref-pointer p-high32 :unsigned-int)))
442 (if (zerop high32)
443 low32
444 (make-64-bit-integer high32 low32)))))
447 (declaim (inline mysql-num-fields))
448 (uffi:def-function "mysql_num_fields"
449 ((res mysql-mysql-res))
450 :returning :unsigned-int
451 :module "mysql")
453 (declaim (inline clsql-mysql-eof))
454 (uffi:def-function ("mysql_eof" clsql-mysql-eof)
455 ((res mysql-mysql-res))
456 :returning :char
457 :module "mysql")
459 (declaim (inline mysql-eof))
460 (defun mysql-eof (res)
461 (if (zerop (clsql-mysql-eof res))
465 (declaim (inline mysql-error))
466 (uffi:def-function ("mysql_error" mysql-error)
467 ((mysql mysql-mysql))
468 :returning :cstring
469 :module "mysql")
471 (declaim (inline mysql-error-string))
472 (defun mysql-error-string (mysql)
473 (uffi:convert-from-cstring (mysql-error mysql)))
475 (declaim (inline mysql-errno))
476 (uffi:def-function "mysql_errno"
477 ((mysql mysql-mysql))
478 :returning :unsigned-int
479 :module "mysql")
481 (declaim (inline mysql-info))
482 (uffi:def-function ("mysql_info" mysql-info)
483 ((mysql mysql-mysql))
484 :returning :cstring
485 :module "mysql")
487 (declaim (inline mysql-info-string))
488 (defun mysql-info-string (mysql)
489 (uffi:convert-from-cstring (mysql-info mysql)))
491 (declaim (inline clsql-mysql-data-seek))
492 (uffi:def-function "clsql_mysql_data_seek"
493 ((res mysql-mysql-res)
494 (offset-high32 :unsigned-int)
495 (offset-low32 :unsigned-int))
496 :module "clsql-mysql"
497 :returning :void)
499 (declaim (inline clsql-mysql-field-name))
500 (uffi:def-function "clsql_mysql_field_name"
501 ((res mysql-field))
502 :module "clsql-mysql"
503 :returning :cstring)
505 (declaim (inline clsql-mysql-field-flags))
506 (uffi:def-function "clsql_mysql_field_flags"
507 ((res mysql-field))
508 :module "clsql-mysql"
509 :returning :unsigned-int)
511 (declaim (inline clsql-mysql-field-type))
512 (uffi:def-function "clsql_mysql_field_type"
513 ((res mysql-field))
514 :module "clsql-mysql"
515 :returning :unsigned-int)
517 (defun mysql-data-seek (res offset)
518 (multiple-value-bind (high32 low32) (split-64-bit-integer offset)
519 (clsql-mysql-data-seek res high32 low32)))