316 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			316 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
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	23 Apr 2003 15:23:43 -0000
 | 
						|
@@ -2,7 +2,8 @@
 | 
						|
 
 | 
						|
 autoheader &&
 | 
						|
 autoconf &&
 | 
						|
-./configure &&
 | 
						|
+./configure --with-iODBC=/afs/wsi/i386_fbsd46 &&
 | 
						|
+##./configure --with-iODBC=/usr/lib &&
 | 
						|
 touch scsh/*.c &&
 | 
						|
 touch build/filenames.scm &&
 | 
						|
 rm -f scheme48.image cig/cig.image scsh/scsh.image &&
 | 
						|
@@ -12,5 +13,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.28
 | 
						|
diff -u -r1.28 configure.in
 | 
						|
--- configure.in	16 Apr 2003 12:41:36 -0000	1.28
 | 
						|
+++ configure.in	23 Apr 2003 15:23:43 -0000
 | 
						|
@@ -373,7 +373,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=$withval ],
 | 
						|
+	[ with_iodbc=no ]
 | 
						|
+	)
 | 
						|
+if test "$with_iodbc" != no; then
 | 
						|
+	odbc_includes="-I$withval/include"
 | 
						|
+	odbc_libs="-liodbc -L$withval/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.61
 | 
						|
diff -u -r1.61 Makefile.in
 | 
						|
--- Makefile.in	10 Mar 2003 12:13:02 -0000	1.61
 | 
						|
+++ Makefile.in	23 Apr 2003 15:23:43 -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/i386_fbsd32/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
 | 
						|
@@ -837,7 +845,10 @@
 | 
						|
 	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-interfaces.scm \
 | 
						|
+	scsh/odbc/odbc-packages.scm \
 | 
						|
+	scsh/odbc/odbc.scm
 | 
						|
 #    	scsh/dbm.scm db.scm ndbm.scm
 | 
						|
 #	jcontrol
 | 
						|
 
 | 
						|
@@ -861,7 +872,9 @@
 | 
						|
 	 $(srcdir)/scsh/rx/packages.scm \
 | 
						|
 	 $(srcdir)/scsh/scsh-package.scm \
 | 
						|
 	 $(srcdir)/scsh/lib/ccp-pack.scm \
 | 
						|
-	 $(srcdir)/scsh/lib/char-package.scm
 | 
						|
+	 $(srcdir)/scsh/lib/char-package.scm \
 | 
						|
+	 $(srcdir)/scsh/odbc/odbc-interfaces.scm \
 | 
						|
+	 $(srcdir)/scsh/odbc/odbc-packages.scm 
 | 
						|
 
 | 
						|
 opens = floatnums scsh ccp-lib scsh-top-package scsh-here-string-hax \
 | 
						|
 	srfi-1 srfi-13 srfi-14 # srfi-14 is also exported by scsh
 | 
						|
 | 
						|
 
 | 
						|
This will add some rules to Makefile and add two options to configure:
 | 
						|
--with-iODBC=PATH and --with-unixODBC=PATH. 
 | 
						|
 | 
						|
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:
 | 
						|
 | 
						|
,open low-odbc
 | 
						|
,open low-odbc-constants
 | 
						|
 | 
						|
(define (get-env-handle)
 | 
						|
  (call-with-values
 | 
						|
    odbc-alloc-environment-handle
 | 
						|
    (lambda (status-code env-handle)
 | 
						|
      (if (odbc-call-successful? status-code)
 | 
						|
	env-handle
 | 
						|
        (error "error allocating environment handle")))))
 | 
						|
 | 
						|
(define (get-conn-handle env-handle)
 | 
						|
  (call-with-values
 | 
						|
    (lambda ()
 | 
						|
      (odbc-alloc-connection-handle env-handle))
 | 
						|
    (lambda (status-code conn-handle)
 | 
						|
      (if (odbc-call-successful? status-code)
 | 
						|
         conn-handle
 | 
						|
         (error "error allocating connection handle")))))
 | 
						|
 | 
						|
(define (get-stmt-handle conn-handle)
 | 
						|
  (call-with-values
 | 
						|
    (lambda ()
 | 
						|
      (odbc-alloc-statement-handle conn-handle))
 | 
						|
    (lambda (status-code stmt-handle)
 | 
						|
      (if (odbc-call-successful? status-code)
 | 
						|
        stmt-handle
 | 
						|
        (error "error allocating statement handle")))))
 | 
						|
 | 
						|
(define env-handle (get-env-handle))
 | 
						|
(define conn-handle (get-conn-handle env-handle))
 | 
						|
 | 
						|
(odbc-sql-connect conn-handle "pgfbsd" "test" "geheim")
 | 
						|
 | 
						|
(define stmt-handle (get-stmt-handle conn-handle))
 | 
						|
 | 
						|
(odbc-sql-execute-direct stmt-handle "select * from abcd")
 | 
						|
 | 
						|
(define col-a (odbc-sql-bindcol stmt-handle 1 sql-c-long 1))
 | 
						|
(define	col-b (odbc-sql-bindcol stmt-handle 2 sql-c-long 1))
 | 
						|
(define col-c (odbc-sql-bindcol stmt-handle 3 sql-c-long 1))
 | 
						|
(define col-d (odbc-sql-bindcol stmt-handle 4 sql-c-char 400))
 | 
						|
 | 
						|
(let lp ((retcode (odbc-sql-fetch stmt-handle))
 | 
						|
	 (result '()))
 | 
						|
  (if (or (odbc-call-successful? retcode) (equal? retcode sql-no-data))
 | 
						|
      (if (equal? retcode sql-no-data)
 | 
						|
	  result
 | 
						|
	  (lp (odbc-sql-fetch stmt-handle)
 | 
						|
	      (cons (list (col-a) (col-b) (col-c) (col-d)) result)))
 | 
						|
      (error "Could not SQLFetch()")))
 | 
						|
 | 
						|
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> |