#!/usr/bin/python

# $Id: sample.py 3633 2010-06-06 23:56:41Z unsaved $

# Sample Python script accessing HyperSQL through the Python pyodbc module.

# This test HyperSQL client uses the ODBC DSN "tstdsn-a" to connect up to a
# HyperSQL server.  Just configure your own DSN to use the HyperSQL ODBC
# driver, specifying the HyperSQL server host name, database name, user,
# password, etc.

# N.b. there is some dependency or bug which requires pyodbc to use the
# ANSI variant of the HyperSQL ODBC Driver.  Using the normal Unicode
# variant will generate the following error message when you try to connect:
#    pyodbc.Error: ('0', '[0] [unixODBC]c (202) (SQLDriverConnectW)')
# It is quite possible that this issue will be taken care of when we fix a
# high-priority bug to do with switching between SQLDriverConnect and
# SQLDriverConnectW on UNIX.

# Author:  Blaine Simpson  (blaine dot simpson at admc dot com)

import pyodbc

# Get a connection handle.
# In addition to the DSN name, you can override or supply additional DSN
# settings, such as "Uid" and "Pwd"; or define the DSN from scratch, starting
# with Driver.  These settings are delimited with "; ".  See pyodbc docs.
conn = pyodbc.connect("DSN=tstdsn-a")
try:
    conn.autocommit = 0

    cursor = conn.cursor();

    cursor.execute("DROP TABLE tsttbl IF EXISTS");
    conn.commit();  # Some recent change to the HyperSQL server or to unixODBC
                    # has made this necessary, at least on UNIX.  Some other
                    # transaction control command would probably be more
                    # appropriate here.

    cursor.execute(
        "CREATE TABLE tsttbl(\n"
        + "    id BIGINT generated BY DEFAULT AS IDENTITY,\n"
        + "    vc VARCHAR(20),\n"
        + "    entrytime TIMESTAMP DEFAULT current_timestamp NOT NULL\n"
        + ")");

    # First a simple/non-parameterized Insertion
    retval = cursor.execute("INSERT INTO tsttbl (id, vc) values (1, 'one')");
    if retval != 1:
        raise Exception(('1st insertion inserted ' + repr(retval)
            + ' rows instead of 1'))
    # Now parameterized.  Unfortunately, the Python DB API and pyodbc API do
    # not allow re-use of a parsed statement.  Cursor must be reparsed for
    # each usage.
    retval = cursor.execute("INSERT INTO tsttbl (id, vc) values (?, ?)",
            2, 'two');
    if retval != 1:
        raise Exception(('2nd insertion inserted ' + repr(retval)
            + ' rows instead of 2'))
    retval = cursor.execute("INSERT INTO tsttbl (id, vc) values (?, ?)",
            3, 'three');
    if retval != 1:
        raise Exception(('3rd insertion inserted ' + repr(retval)
            + ' rows instead of 3'))
    retval = cursor.execute("INSERT INTO tsttbl (id, vc) values (?, ?)",
            4, 'four');
    if retval != 1:
        raise Exception(('4th insertion inserted ' + repr(retval)
            + ' rows instead of 4'))
    retval = cursor.execute("INSERT INTO tsttbl (id, vc) values (?, ?)",
            5, 'five');
    if retval != 1:
        raise Exception(('5th insertion inserted ' + repr(retval)
            + ' rows instead of 5'))
    conn.commit();

    # Non-parameterized query
    for row in cursor.execute(
            "SELECT * FROM tsttbl WHERE id < 3"):
        print row

    # Non-parameterized query.  As noted above, can't re-use parsed cursor.
    for row in cursor.execute(
            "SELECT * FROM tsttbl WHERE id > ?", 3):
        # For variety, we format the files ourselves this time
        print repr(row.ID) + '|' + row.VC + '|' + repr(row.ENTRYTIME)

except Exception as e:
    conn.rollback();
    raise e

finally:
    conn.close();
