scsh-0.6/scsh/odbc
eknauel 2c1385f136 + fixed various bugs introduced in last version 2003-03-20 16:28:50 +00:00
..
README + use unified patch format 2003-03-20 16:04:23 +00:00
generate-constants.scm Even more constants from sqlext.h 2003-02-08 13:15:40 +00:00
odbc-bindcol.scm + This version introduces the all new SQLBindCol(), which might (in 2002-09-30 18:20:47 +00:00
odbc-constants.c Even more constants from sqlext.h 2003-02-08 13:15:40 +00:00
odbc-constants.scm + fixed various bugs introduced in last version 2003-03-20 16:28:50 +00:00
odbc-types.scm Scheme records for ODBC structures date, time, timestamp and numeric 2002-08-29 13:49:14 +00:00
odbc.c + fixed various bugs introduced in last version 2003-03-20 16:28:50 +00:00
odbc.h - Support for odbc 1.0 alloc functions 2002-10-11 08:06:45 +00:00
odbc.scm + fixed various bugs introduced in last version 2003-03-20 16:28:50 +00:00
scshql.scm Initial version of scshql: The original scsh ODBC API for 0.5.x 2002-12-09 16:14:48 +00:00

README

ODBC support for scsh 0.6.x
===========================

This directory contains bindings to Unix ODBC libraries, which make it
possible to call any ODBC functions from scsh directly. At the moment
ODBC support is not part of the scsh distribution, since ODBC support
is in an early stage of development -- to put it another way, it's for
thrill seekers only! The code is complete, but needs testing. So,
please let us know if you find a bug. ODBC supports also lacks some
documentation. 

1. Building scsh with ODBC support

I recommend to use the scsh version from CVS. However, it might work
with scsh-releases 0.6.1 or newer to. Be sure to have a ODBC
implementation for Unix, like unixODBC or iODBC -- both seem to work
fine. Apply the following patch:

Index: autogen.sh
===================================================================
RCS file: /cvsroot/scsh/scsh-0.6/autogen.sh,v
retrieving revision 1.7
diff -u -r1.7 autogen.sh
--- autogen.sh	12 Feb 2002 16:26:05 -0000	1.7
+++ autogen.sh	20 Mar 2003 16:01:57 -0000
@@ -2,7 +2,7 @@
 
 autoheader &&
 autoconf &&
-./configure &&
+./configure --with-iODBC=/usr/lib &&
 touch scsh/*.c &&
 touch build/filenames.scm &&
 rm -f scheme48.image cig/cig.image scsh/scsh.image &&
@@ -12,5 +12,4 @@
 make i-know-what-i-am-doing &&
 make c/scheme48.h&&
 make linker &&
-make build/initial.image &&
-make distclean 
+make build/initial.image 
Index: configure.in
===================================================================
RCS file: /cvsroot/scsh/scsh-0.6/configure.in,v
retrieving revision 1.27
diff -u -r1.27 configure.in
--- configure.in	13 Dec 2002 15:22:13 -0000	1.27
+++ configure.in	20 Mar 2003 16:01:57 -0000
@@ -394,7 +394,30 @@
      AC_SUBST(LIBS)
      AC_SUBST(TMPDIR)
 
-    
+AC_ARG_WITH(unixODBC,
+	[ --with-unixODBC=DIR 		Support for unixODBC ],
+	[ with_unixodbc=$withval ],
+	[ with_unixodbc=no ]
+	)
+if test "$with_unixodbc" != no; then
+	odbc_includes="-I$with_unixodbc/include"
+	odbc_libs="-lodbc -L$with_unixodbc/lib"
+	AC_SUBST(odbc_includes)
+	AC_SUBST(odbc_libs)
+fi	
+
+AC_ARG_WITH(iODBC,
+	[ --with-iODBC=DIR			Support for iODBC ],
+	[ with_iodbc=$with_iodbc ],
+	[ with_iodbc=no ]
+	)
+if test "$with_iodbc" != no; then
+	odbc_includes="-I$with_iodbc/include"
+	odbc_libs="-liodbc -L$with_iodbc/lib"
+	AC_SUBST(odbc_includes)
+	AC_SUBST(odbc_libs)
+fi	
+
 AC_CONFIG_FILES(Makefile scsh/endian.scm scsh-config)
 AC_CONFIG_COMMANDS([scsh-config+x],[chmod +x scsh-config])
 AC_OUTPUT
Index: Makefile.in
===================================================================
RCS file: /cvsroot/scsh/scsh-0.6/Makefile.in,v
retrieving revision 1.59
diff -u -r1.59 Makefile.in
--- Makefile.in	13 Jan 2003 06:17:49 -0000	1.59
+++ Makefile.in	20 Mar 2003 16:01:57 -0000
@@ -8,8 +8,8 @@
 VPATH = @srcdir@
 CC = @CC@
 DEFS = @DEFS@
-LIBS = @LIBS@
-CFLAGS = @CFLAGS@
+LIBS = @LIBS@ @odbc_libs@
+CFLAGS = @CFLAGS@ @odbc_includes@
 INSTALL = @INSTALL@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_DATA = @INSTALL_DATA@
@@ -47,7 +47,8 @@
 # BUILD_RUNNABLE has to be Scheme 48 0.53. This is used for builds directly 
 # out of the CVS repository.
 # We cannot use Scsh here since -i is not understood.
-BUILD_RUNNABLE = /afs/wsi/i386_fbsd32/bin/scheme48
+BUILD_RUNNABLE = /afs/wsi/ppc_macx55/scheme48-0.53/bin/scheme48
+#BUILD_RUNNABLE = /afs/wsi/ppc_macx55/scheme48-0.53/bin/scheme48
 RUNNABLE = scsh
 MANPAGE = $(RUNNABLE).$(manext)
 LIB = $(libdir)/$(RUNNABLE)
@@ -133,7 +134,7 @@
 	scsh/userinfo1.o \
 	scsh/sighandlers1.o \
 	scsh/libscsh.o \
-	scsh/md5.o
+	scsh/md5.o 
 
 SCSH_INITIALIZERS = s48_init_syslog s48_init_posix_regexp \
 	s48_init_userinfo s48_init_sighandlers \
@@ -169,16 +170,23 @@
 # External code to include in the VM
 # After changing any of these you should delete `scheme48vm' and remake it.
 
-EXTERNAL_OBJECTS = $(SOCKET_OBJECTS) $(LOOKUP_OBJECTS)
-EXTERNAL_FLAGS = $(SOCKET_FLAGS)
+EXTERNAL_OBJECTS = $(SOCKET_OBJECTS) $(LOOKUP_OBJECTS) $(ODBC_OBJECTS)
+EXTERNAL_FLAGS = $(SOCKET_FLAGS) $(ODBC_FLAGS)
+EXTERNAL_LDFLAGS = $(SOCKET_LD_FLAGS) $(ODBC_LD_FLAGS)
 EXTERNAL_INITIALIZERS = $(ADDITIONAL_INITIALIZER) $(SOCKET_INITIALIZERS) 	\
 	$(LOOKUP_INITIALIZERS) 							\
 	$(SCSH_INITIALIZERS) $(SRFI_INITIALIZERS)				\
+	$(ODBC_INITIALIZERS) 							\
 	s48_init_cig
 
 
 # Rules for any external code.
 
+scsh/odbc/odbc.o: scsh/odbc/odbc.h
+
+ODBC_OBJECTS = scsh/odbc/odbc.o
+ODBC_INITIALIZERS = s48_init_odbc
+
 # Socket rules
 
 c/unix/socket.o: c/scheme48.h c/fd-io.h c/event.h
@@ -835,7 +843,8 @@
 	scsh/rx/re-high.scm \
 	scsh/rx/regexp.scm \
 	scsh/rx/re-low.scm \
-	scsh/rx/regress.scm
+	scsh/rx/regress.scm \
+	scsh/odbc/odbc.scm
 #    	scsh/dbm.scm db.scm ndbm.scm
 #	jcontrol
 

This will add some rules to Makefile and add two options to configure:
--with-iODBC=PATH and --with-unixODBC=PATH. 

This patch will add a module odbc to the package configuration. With
this patch, it's possible to type ,open odbc at the scsh prompt to
load all the beautiful ODBC functions into scsh:

Index: scsh-package.scm
===================================================================
RCS file: /cvsroot/scsh/scsh-0.6/scsh/scsh-package.scm,v
retrieving revision 1.59
diff -u -r1.59 scsh-package.scm
--- scsh-package.scm	25 Feb 2003 12:58:37 -0000	1.59
+++ scsh-package.scm	20 Mar 2003 16:03:38 -0000
@@ -597,3 +597,21 @@
       signals
       srfi-9)
   (files srfi-19))
+
+;;; ODBC stuff
+
+(define-structure odbc-data-types odbc-data-types-interface
+  (open 
+   scheme define-structure
+   external-calls)
+  (files (odbc odbc-types)))
+
+(define-structure odbc odbc-interface
+  (open 
+	scheme define-record-types
+	external-calls
+	scsh-utilities 
+	conditions signals)
+  (files (odbc odbc)
+	 (odbc odbc-bindcol)))
+
Index: scsh-interfaces.scm
===================================================================
RCS file: /cvsroot/scsh/scsh-0.6/scsh/scsh-interfaces.scm,v
retrieving revision 1.53
diff -u -r1.53 scsh-interfaces.scm
--- scsh-interfaces.scm	25 Feb 2003 12:58:37 -0000	1.53
+++ scsh-interfaces.scm	20 Mar 2003 16:03:39 -0000
@@ -1166,13 +1166,13 @@
   (export crypt))
 
 (define-interface uname-interface
-  (export uname
-	  uname:os-name
-	  uname:node-name
-	  uname:release
-	  uname:version
-	  uname:machine
-	  type/uname))
+   (export uname
+ 	  uname:os-name
+ 	  uname:node-name
+ 	  uname:release
+ 	  uname:version
+ 	  uname:machine
+ 	  type/uname))
 
 (define-interface md5-interface
   (export make-md5-context
@@ -1275,3 +1275,92 @@
    ;; Date to string/string to date converters.
    date->string
    string->date))
+
+;;; ODBC stuff
+(define-interface odbc-data-types-interface
+  (export 
+
+   make-sql-date
+   sql-date?
+   sql-date-year
+   sql-date-month
+   sql-date-day
+
+   make-sql-time
+   sql-time?
+   sql-time-hour
+   sql-time-minute
+   sql-time-second
+
+   make-sql-timestamp
+   sql-timestamp?
+   sql-timestamp-year
+   sql-timestamp-month
+   sql-timestamp-day
+   sql-timestamp-hour
+   sql-timestamp-minute
+   sql-timestamp-second
+   sql-timestamp-fraction
+
+   make-sql-numeric
+   sql-numeric?
+   sql-numeric-precision
+   sql-numeric-scale
+   sql-numeric-sign
+   sql-numeric-value))
+
+(define-interface odbc-interface
+  (export 
+   odbc-handle?
+   environment-handle?
+   connection-handle?
+   statement-handle?
+   descriptor-handle?
+   
+   odbc-alloc-environment-handle
+   odbc-alloc-connection-handle
+   odbc-alloc-statement-handle
+   odbc-sql-connect
+
+   odbc-sql-data-sources
+   odbc-sql-drivers
+   odbc-sql-get-info-int
+   odbc-sql-get-info-string
+   odbc-sql-get-func
+   odbc-sql-get-type-info
+
+   odbc-sql-set-connect-attr-int
+   odbc-sql-set-connect-attr-string
+   odbc-sql-get-connect-attr-string
+   odbc-sql-get-connect-attr-int
+   odbc-sql-set-env-attr-int
+   odbc-sql-get-env-attr-int
+   odbc-sql-set-stmt-attr-int
+   odbc-sql-get-stmt-attr-int
+
+   odbc-sql-prepare
+   odbc-sql-bind-parameter-exec-out
+   odbc-sql-get-cursor-name
+   odbc-sql-set-cursor-name
+
+   odbc-sql-execute
+   odbc-sql-execute-direct
+   
+   odbc-sql-row-count
+   odbc-sql-get-data
+   odbc-sql-fetch
+   
+   odbc-sql-free-statement
+   odbc-sql-close-cursor
+   odbc-sql-cancel
+   odbc-sql-num-result-cols
+   odbc-sql-describe-col
+   
+   odbc-sql-disconnect
+   odbc-sql-free-handle
+
+   odbc-buffer-exceeded?
+   signal-buffer-exceeded
+   odbc-unbound-column?
+   signal-unbound-column
+   odbc-sql-bindcol))

Now it's time to build scsh. Edit the call to configure in autgen.sh to
your needs, e.g.:

./configure --with-iODBC=/usr/local &&

Don't forget the && at the end of line! Now, run autogen.sh to build
the VM and all that stuff. Run make to build scsh. If the build
suceeds, tap yourself on the shoulder, that's important, it might the
last sense of achievement from now on.

2. Running scsh with ODBC support

Type ./scshvm -i scsh/scsh.image -- that's it!

3. How do I use ODBC support?

If you installed the odbc-module-patch, simply type ,open odbc. If you
have installed dynamic ODBC libraries make sure your system can find
them, e.g. put the path in your LD_LIBRARY_PATH. This should look like
this:

[knauel@jimi scsh-0.6.cvs] ./scshvm -i scsh/scsh.image 
Welcome to scsh 0.6.3 (Health Reform)
Type ,? for help.
> ,open odbc
Load structure odbc (y/n)? y
[odbc ./scsh/odbc/odbc-bindcol.scm ./scsh/odbc/odbc.scm]
> ,exit

This is an example entry for ~/.odbc.ini:

[test]
DSN 	= mysql1
Driver	= /afs/informatik.uni-tuebingen.de/pu/src/build/knauel/i386_fbsd43/lib/libmyodbc3.so
Server	= localhost
Port	= 3306
User	= odbc
Password= geheim
TraceFile= stderr
Trace	= on

It may be necessary to help your ODBC driver manager to find that file
be setting the environment variable ODBCINI.

Let's see what data sources are known to the system:

(let* ((env-handle (odbc-alloc-environment-handle))
       (data-sources (odbc-sql-data-sources env-handle)))
  (for-each 
   (lambda (pair)
     (display "data source: ")
     (display (car pair))
     (newline)
     (display "using driver: ")
     (display (cdr pair))
     (newline))
   data-sources))

Don't worry about freeing handles -- this will happen automatically
when the scheme variable gets garbage collected.

This example shows how you can read the information from ODBC's
diag-recs in case an error occurs, which is to happen very likely: 

(define (display-errors handle)
  (let ((recs (odbc-sql-get-diag-recs handle)))
    (if (not (null? recs))
	(for-each (lambda (rec)
		    (newline)
		    (display "state: ")
		    (display (odbc-diag-sql-state rec))
		    (newline)
		    (display "native error: ")
		    (display (odbc-diag-native-error rec))
		    (newline)
		    (display "message: ")
		    (display (odbc-diag-message rec))
		    (newline))
		  recs)
	(begin
	  (display "No error messages (so far ;-)")
	  (newline)))))

Not let's read some stuff from the database! Say we have a database
with four columns a through d, where a,b,c are integer columns and d
is text. Using the fancy odbc-sql-bindcol functions that's pretty
easy:

(define env-handle 
  (odbc-alloc-environment-handle))

(define conn-handle 
  (odbc-alloc-connection-handle env-handle))

(odbc-sql-connect conn-handle "test" "odbc" "geheim")

(define stmt-handle (odbc-alloc-statement-handle conn-handle))

(odbc-sql-execute-direct stmt-handle "select * from abc")

(define col-a (odbc-sql-bindcol stmt-handle 1 sql-type-c-long 1))
(define	col-b (odbc-sql-bindcol stmt-handle 2 sql-type-c-long 1))
(define col-c (odbc-sql-bindcol stmt-handle 3 sql-type-c-long 1))
(define col-d (odbc-sql-bindcol  stmt-handle 4 sql-type-c-char 400))

(let lp ((retcode (odbc-sql-fetch stmt-handle))
	 (result '()))
  (if (equal? retcode sql-no-data)
      result
      (lp (odbc-sql-fetch stmt-handle)
	  (cons (list (col-a) (col-b) (col-c) (col-d)) result))))

Please let me know, if you find some bugs. I hereby promise to
complete the documentation as soon as possible!

Eric Knauel <knauel@informatik.uni-tuebingen.de>