Ruby, Python & ODBC

I recently tried extracting data from an Access database using Ruby and ODBC.  The first challenge is that Windows ODBC drivers can be either 32 or 64-bit.  On a 64-bit host only the 64-bit configuration panel is present in the control panel, and the 32-bit panel must be accessed directly by invoking C:WindowsSysWOW64odbcad32.exe.  More seriously, however, the ruby-odbc home page only lists Win32 binaries compiled using Microsoft Visual C, but the popular RubyInstaller for Windows distribution is compiled with MinGW making the two effectively incompatible.

Contrast this with Python which has pyodbc downloads compatible with the canonical distribution from python.org, even if trailing the latest release.  For enterprise applications there is even a commercial ODBC driver supported by egenix.

Both Ruby and Python also have DBI interfaces, but Python DBI has been deprecated, and for Ruby the DBD-ODBC implementation relies on the same underlying ruby-odbc package.  For now it looks like I’ll be sticking with Python for ODBC.

Google Trends – Databases & Languages

Google Trends is a great tool for graphing search term popularity over time. Here is a comparison of searches for several makes of database.

ScreenShot001 

Perhaps it’s a quirk of the phrases I used, but I was surprised to see Oracle so dominant, and even MySQL more popular than SQL Server.  PostgreSQL languishes in obscurity compared to MySQL, and Ingres barely registers at all.

Here’s some languages that I’m interested in.  Java is hugely dominant.

ScreenShot003

Let’s take out Java and zoom in.  I was surprised to see Ruby’s recent decline relative to Python.  Books on Scala have come out only recently.

ScreenShot001

Looking more specifically at JVM language dialects I’m surprised to see Jython competing so strongly with JRuby.  I’m not sure if I picked the right phrase for Groovy.

ScreenShot002

Choosing tools solely on the basis of popularity is obviously not a great idea, but I do feel better now about continuing to use Oracle, Java and Python.

P.S. See also the TIOBE Programming Community Index

cx_Oracle callfunc()

I like wrapping database queries in stored procedures: it keeps the SQL in the database, where Oracle can track its dependencies and flag if some change makes it invalid.  Here’s an example using Oracle’s demo schema SCOTT:

CREATE OR REPLACE PACKAGE emp_extract_k
AS
   TYPE emp_t
   IS
      RECORD( ename  varchar2( 10 ), hiredate date, sal     number( 7, 2 ) );
   TYPE emp_csr_t IS REF CURSOR
      RETURN emp_t;
   FUNCTION get_emps
      RETURN emp_csr_t;
END;
/
CREATE OR REPLACE PACKAGE BODY emp_extract_k
AS
   FUNCTION get_emps
      RETURN emp_csr_t
   IS
      c   emp_csr_t;
   BEGIN
      OPEN c FOR SELECT   ename, hiredate, sal FROM scott.emp;
      RETURN c;
   END;
END;/

Now suppose I want to take the output from a stored procedure like the one above and write it to a CSV file.  In Python this is trivially easy:

 import cx_Oracle
 import csv
 reportName = 'emp_extract_k.get_emps'
 connection = cx_Oracle.connect(userid)
 cursor = connection.cursor()
 rs = cursor.callfunc(reportName, cx_Oracle.CURSOR)
 fd = open(reportName+'.csv', 'w')
 csvFile = csv.writer(fd)
 header = []
 [header.append(col_defn[0]) for col_defn in rs.description]
 csvFile.writerow(header)
 for r in rs:
  csvFile.writerow(r)
 fd.close()