From: Peter T Mount <peter@retep.org.uk>

This implements some of the JDBC2 methods, fixes a bug introduced into the
JDBC1 portion of the driver, and introduces a new example, showing how to
use the CORBA ORB thats in Java2 with JDBC.

The Tar file contains the new files, the diff the changes to the others.
CHANGELOG is separate as I forgot to make a .orig ;-)
This commit is contained in:
Marc G. Fournier 1999-01-25 21:22:06 +00:00
parent 1401f63dd1
commit 2ee522954d
12 changed files with 879 additions and 10 deletions

View File

@ -1,3 +1,12 @@
Mon Jan 25 19:45:00 GMT 1999
- created subfolders example/corba and example/corba/idl to hold the
new example showing how to hook CORBA and PostgreSQL via JDBC
- implemented some JDBC2 methods curtesy of Joachim.Gabler@t-online.de
Sat Jan 23 10:30:00 GMT 1999
- Changed imports in postgresql.jdbc1.ResultSetMetaData as for some
reason it didn't want to compile under jdk1.1.6
Tue Dec 29 15:45:00 GMT 1998
- Refreshed the README (which was way out of date)

View File

@ -4,16 +4,18 @@
# Makefile for Java JDBC interface
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/Makefile,v 1.11 1999/01/17 04:51:49 momjian Exp $
# $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/Makefile,v 1.12 1999/01/25 21:22:02 scrappy Exp $
#
#-------------------------------------------------------------------------
FIND = find
IDL2JAVA = idltojava -fno-cpp -fno-tie
JAR = jar
JAVA = java
JAVAC = javac
JAVADOC = javadoc
RM = rm -f
TOUCH = touch
# This defines how to compile a java class
.java.class:
@ -44,6 +46,9 @@ all: makeVersion.class
@echo ------------------------------------------------------------
@echo To build the examples, type:
@echo " make examples"
@echo
@echo "To build the CORBA example (requires Java2):"
@echo " make corba"
@echo ------------------------------------------------------------
@echo
@ -142,7 +147,8 @@ clean:
$(FIND) . -name "*~" -exec $(RM) {} \;
$(FIND) . -name "*.class" -exec $(RM) {} \;
$(FIND) . -name "*.html" -exec $(RM) {} \;
$(RM) postgresql.jar
-$(RM) -rf stock example/corba/stock.built
-$(RM) postgresql.jar
-$(RM) -rf Package-postgresql *output
#######################################################################
@ -219,7 +225,37 @@ example/blobtest.class: example/blobtest.java
example/datestyle.class: example/datestyle.java
example/psql.class: example/psql.java
example/ImageViewer.class: example/ImageViewer.java
#example/Objects.class: example/Objects.java
example/threadsafe.class: example/threadsafe.java
example/metadata.class: example/metadata.java
#######################################################################
#
# CORBA This extensive example shows how to integrate PostgreSQL
# JDBC & CORBA.
CORBASRC = $(wildcard example/corba/*.java)
CORBAOBJ = $(subst .java,.class,$(CORBASRC))
corba: jdbc2 example/corba/stock.built $(CORBAOBJ)
@echo -------------------------------------------------------
@echo The corba example has been built. Before running, you
@echo will need to read the example/corba/readme file on how
@echo to run the example.
@echo
#
# This compiles our idl file and the stubs
#
# Note: The idl file is in example/corba, but it builds a directory under
# the current one. For safety, we delete that directory before running
# idltojava
#
example/corba/stock.built: example/corba/stock.idl
-rm -rf stock
$(IDL2JAVA) $<
$(JAVAC) stock/*.java
$(TOUCH) $@
# tip: we cant use $(wildcard stock/*.java) in the above rule as a race
# condition occurs, where javac is passed no arguments
#######################################################################

View File

@ -0,0 +1,288 @@
package example.corba;
import java.io.*;
import java.sql.*;
import org.omg.CosNaming.*;
/**
* This class is the frontend to our mini CORBA application.
*
* It has no GUI, just a text frontend to keep it simple.
*
* $Id: StockClient.java,v 1.1 1999/01/25 21:22:03 scrappy Exp $
*/
public class StockClient
{
org.omg.CosNaming.NamingContext nameService;
stock.StockDispenser dispenser;
stock.StockItem item;
BufferedReader in;
public StockClient(String[] args) {
try {
// We need this for our IO
in = new BufferedReader(new InputStreamReader(System.in));
// Initialize the orb
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);
// Get a reference to the Naming Service
org.omg.CORBA.Object nameServiceObj = orb.resolve_initial_references("NameService");
if(nameServiceObj==null) {
System.err.println("nameServiceObj == null");
return;
}
nameService = org.omg.CosNaming.NamingContextHelper.narrow(nameServiceObj);
if(nameService==null) {
System.err.println("nameService == null");
return;
}
// Resolve the dispenser
NameComponent[] dispName = {
new NameComponent("StockDispenser","Stock")
};
dispenser = stock.StockDispenserHelper.narrow(nameService.resolve(dispName));
if(dispenser==null) {
System.err.println("dispenser == null");
return;
}
// Now run the front end.
run();
} catch(Exception e) {
System.out.println(e.toString());
e.printStackTrace();
System.exit(1);
}
}
public static void main(String[] args) {
new StockClient(args);
}
public void run() {
// First reserve a StockItem
try {
item = dispenser.reserveItem();
} catch(Exception e) {
System.out.println(e.toString());
e.printStackTrace();
System.exit(1);
}
mainMenu();
// finally free the StockItem
try {
dispenser.releaseItem(item);
} catch(Exception e) {
System.out.println(e.toString());
e.printStackTrace();
System.exit(1);
}
}
private void mainMenu() {
boolean run=true;
while(run) {
System.out.println("\nCORBA Stock System\n");
System.out.println(" 1 Display stock item");
System.out.println(" 2 Remove item from stock");
System.out.println(" 3 Put item into stock");
System.out.println(" 4 Order item");
System.out.println(" 5 Display all items");
System.out.println(" 0 Exit");
int i = getMenu("Main",5);
switch(i)
{
case 0:
run=false;
break;
case 1:
displayItem();
break;
case 2:
bookOut();
break;
case 3:
bookIn();
break;
case 4:
order(0);
break;
case 5:
displayAll();
break;
}
}
}
private void displayItem() {
try {
int id = getMenu("\nStockID to display",item.getLastID());
if(id>0) {
item.fetchItem(id);
System.out.println("========================================");
String status = "";
if(!item.isItemValid())
status=" ** Superceded **";
int av = item.getAvailable();
System.out.println(" Stock ID: "+id+status+
"\nItems Available: "+av+
"\nItems on order: "+item.getOrdered()+
"\n Description: "+item.getDescription());
System.out.println("========================================");
if(av>0)
if(yn("Take this item out of stock?")) {
int rem=1;
if(av>1)
rem=getMenu("How many?",av);
if(rem>0)
item.removeStock(rem);
}
}
} catch(Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
}
private void bookOut() {
try {
int id = getMenu("\nStockID to take out",item.getLastID());
if(id>0) {
item.fetchItem(id);
int av = item.getAvailable();
if(av>0)
if(yn("Take this item out of stock?")) {
int rem=1;
if(av>1)
rem=getMenu("How many?",av);
if(rem>0)
item.removeStock(rem);
}
else {
System.out.println("This item is not in stock.");
int order = item.getOrdered();
if(order>0)
System.out.println("There are "+item.getOrdered()+" items on order.");
else {
if(item.isItemValid()) {
System.out.println("You will need to order some more "+item.getDescription());
order(id);
} else
System.out.println("This item is now obsolete");
}
}
} else
System.out.println(item.getDescription()+"\nThis item is out of stock");
} catch(Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
}
// book an item into stock
private void bookIn() {
try {
int id = getMenu("\nStockID to book in",item.getLastID());
item.fetchItem(id);
System.out.println(item.getDescription());
if(item.getOrdered()>0) {
int am = getMenu("How many do you want to book in",item.getOrdered());
if(am>0)
item.addNewStock(am);
} else
System.out.println("You don't have any of this item on ordered");
} catch(Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
}
// Order an item
private void order(int id) {
try {
if(id==0)
id = getMenu("\nStockID to order",item.getLastID());
item.fetchItem(id);
System.out.println(item.getDescription());
int am = getMenu("How many do you want to order",999);
if(am>0)
item.orderStock(am);
} catch(Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
}
private void displayAll() {
try {
boolean cont=true;
int nr=item.getLastID();
String header = "\nId\tAvail\tOrdered\tDescription";
System.out.println(header);
for(int i=1;i<=nr && cont;i++) {
item.fetchItem(i);
System.out.println(""+i+"\t"+item.getAvailable()+"\t"+item.getOrdered()+"\t"+item.getDescription());
if((i%20)==0) {
if((cont=yn("Continue?")))
System.out.println(header);
}
}
} catch(Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
}
private int getMenu(String title,int max) {
int v=-1;
while(v<0 || v>max) {
System.out.print(title);
System.out.print(" [0-"+max+"]: ");
System.out.flush();
try {
v = Integer.parseInt(in.readLine());
} catch(Exception nfe) {
v=-1;
}
}
return v;
}
private boolean yn(String title) {
try {
while(true) {
System.out.print(title);
System.out.flush();
String s = in.readLine();
if(s.startsWith("y") || s.startsWith("Y"))
return true;
if(s.startsWith("n") || s.startsWith("N"))
return false;
}
} catch(Exception nfe) {
System.out.println(nfe.toString());
nfe.printStackTrace();
System.exit(1);
}
return false;
}
}

View File

@ -0,0 +1,117 @@
package example.corba;
import java.sql.*;
/**
* This class handles the JDBC side of things. It opens a connection to
* the database, and performes queries on that database.
*
* In essence, you could use this class on it's own. The rest of the classes
* in this example handle either the CORBA mechanism, or the frontend.
*
* Note: Before you ask, why perform a query on each call, you have to remember
* that an object could be changed by another client, and we need to ensure that
* the returned data is live and accurate.
*
* $Id: StockDB.java,v 1.1 1999/01/25 21:22:03 scrappy Exp $
*/
public class StockDB
{
Connection con;
Statement st;
// the current stock number
int id = -1;
public void connect(String url,String usr,String pwd) throws Exception {
Class.forName("postgresql.Driver");
System.out.println("Connecting to "+url);
con = DriverManager.getConnection(url,usr,pwd);
st = con.createStatement();
}
public void closeConnection() throws Exception {
con.close();
}
public void fetchItem(int id) throws Exception {
this.id = id;
}
public int newItem() throws Exception {
// tba
return -1;
}
public String getDescription() throws SQLException {
ResultSet rs = st.executeQuery("select description from stock where id="+id);
if(rs!=null) {
rs.next();
String s = rs.getString(1);
rs.close();
return s;
}
throw new SQLException("No ResultSet");
}
public int getAvailable() throws SQLException {
ResultSet rs = st.executeQuery("select avail from stock where id="+id);
if(rs!=null) {
rs.next();
int v = rs.getInt(1);
rs.close();
return v;
}
throw new SQLException("No ResultSet");
}
public int getOrdered() throws SQLException {
ResultSet rs = st.executeQuery("select ordered from stock where id="+id);
if(rs!=null) {
rs.next();
int v = rs.getInt(1);
rs.close();
return v;
}
throw new SQLException("No ResultSet");
}
public boolean isItemValid() throws SQLException {
ResultSet rs = st.executeQuery("select valid from stock where id="+id);
if(rs!=null) {
rs.next();
boolean b = rs.getBoolean(1);
rs.close();
return b;
}
throw new SQLException("No ResultSet");
}
public void addNewStock(int amount) throws SQLException {
st.executeUpdate("update stock set avail=avail+"+amount+
", ordered=ordered-"+amount+
" where id="+id+" and ordered>="+amount);
}
public void removeStock(int amount) throws SQLException {
st.executeUpdate("update stock set avail=avail-"+amount+
" where id="+id);
}
public void orderStock(int amount) throws SQLException {
st.executeUpdate("update stock set ordered=ordered+"+amount+
" where id="+id);
}
public int getLastID() throws SQLException {
ResultSet rs = st.executeQuery("select max(id) from stock");
if(rs!=null) {
rs.next();
int v = rs.getInt(1);
rs.close();
return v;
}
throw new SQLException("No ResultSet");
}
}

View File

@ -0,0 +1,83 @@
package example.corba;
import org.omg.CosNaming.*;
/**
* This class implements the server side of the example.
*
* $Id: StockDispenserImpl.java,v 1.1 1999/01/25 21:22:03 scrappy Exp $
*/
public class StockDispenserImpl extends stock._StockDispenserImplBase
{
private int maxObjects = 10;
private int numObjects = 0;
private StockItemStatus[] stock = new StockItemStatus[maxObjects];
public StockDispenserImpl(String[] args,String name,int num)
{
super();
try {
// get reference to orb
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);
// prestart num objects
if(num>=maxObjects)
num=maxObjects;
numObjects = num;
for(int i=0;i<numObjects;i++) {
stock[i] = new StockItemStatus();
stock[i].ref = new StockItemImpl(args,"StockItem"+(i+1));
orb.connect(stock[i].ref);
}
} catch(org.omg.CORBA.SystemException e) {
e.printStackTrace();
}
}
/**
* This method, defined in stock.idl, reserves a slot in the dispenser
*/
public stock.StockItem reserveItem() throws stock.StockException
{
for(int i=0;i<numObjects;i++) {
if(!stock[i].inUse) {
stock[i].inUse = true;
System.out.println("Reserving slot "+i);
return stock[i].ref;
}
}
return null;
}
/**
* This releases a slot from the dispenser
*/
public void releaseItem(stock.StockItem item) throws stock.StockException
{
for(int i=0;i<numObjects;i++) {
if(stock[i].ref.getInstanceName().equals(item.getInstanceName())) {
stock[i].inUse = false;
System.out.println("Releasing slot "+i);
return;
}
}
System.out.println("Reserved object not a member of this dispenser");
return;
}
/**
* This class defines a slot in the dispenser
*/
class StockItemStatus
{
StockItemImpl ref;
boolean inUse;
StockItemStatus() {
ref = null;
inUse = false;
}
}
}

View File

@ -0,0 +1,163 @@
package example.corba;
import org.omg.CosNaming.*;
/**
* This class implements the server side of the example.
*
* $Id: StockItemImpl.java,v 1.1 1999/01/25 21:22:04 scrappy Exp $
*/
public class StockItemImpl extends stock._StockItemImplBase
{
private StockDB db;
private String instanceName;
public StockItemImpl(String[] args,String iname) {
super();
try {
db =new StockDB();
db.connect(args[1],args[2],args[3]);
System.out.println("StockDB object "+iname+" created");
instanceName = iname;
} catch(Exception e) {
e.printStackTrace();
}
}
/**
* This is defined in stock.idl
*
* It sets the item to view
*/
public void fetchItem(int id) throws stock.StockException {
try {
db.fetchItem(id);
} catch(Exception e) {
throw new stock.StockException(e.toString());
}
}
/**
* This is defined in stock.idl
*
* It sets the item to view
*/
public int newItem() throws stock.StockException {
try {
return db.newItem();
} catch(Exception e) {
throw new stock.StockException(e.toString());
}
}
/**
* This is defined in stock.idl
*
* It returns the description of a Stock item
*/
public String getDescription() throws stock.StockException {
try {
return db.getDescription();
} catch(Exception e) {
throw new stock.StockException(e.toString());
}
}
/**
* This is defined in stock.idl
*
* It returns the description of a Stock item
*/
public int getAvailable() throws stock.StockException {
try {
return db.getAvailable();
} catch(Exception e) {
throw new stock.StockException(e.toString());
}
}
/**
* This is defined in stock.idl
*
* It returns the description of a Stock item
*/
public int getOrdered() throws stock.StockException {
try {
return db.getOrdered();
} catch(Exception e) {
throw new stock.StockException(e.toString());
}
}
/**
* This is defined in stock.idl
*
* It returns the description of a Stock item
*/
public boolean isItemValid() throws stock.StockException {
try {
return db.isItemValid();
} catch(Exception e) {
throw new stock.StockException(e.toString());
}
}
/**
* This is defined in stock.idl
*
* It returns the description of a Stock item
*/
public void addNewStock(int id) throws stock.StockException {
try {
db.addNewStock(id);
} catch(Exception e) {
throw new stock.StockException(e.toString());
}
}
/**
* This is defined in stock.idl
*
* It returns the description of a Stock item
*/
public void removeStock(int id) throws stock.StockException {
try {
db.removeStock(id);
} catch(Exception e) {
throw new stock.StockException(e.toString());
}
}
/**
* This is defined in stock.idl
*
* It returns the description of a Stock item
*/
public void orderStock(int id) throws stock.StockException {
try {
db.orderStock(id);
} catch(Exception e) {
throw new stock.StockException(e.toString());
}
}
/**
* This returns the highest id used, hence the number of items available
*/
public int getLastID() throws stock.StockException {
try {
return db.getLastID();
} catch(Exception e) {
throw new stock.StockException(e.toString());
}
}
/**
* This is used by our Dispenser
*/
public String getInstanceName() {
return instanceName;
}
}

View File

@ -0,0 +1,53 @@
package example.corba;
import org.omg.CosNaming.*;
/**
* This class implements the server side of the example.
*
* $Id: StockServer.java,v 1.1 1999/01/25 21:22:04 scrappy Exp $
*/
public class StockServer
{
public static void main(String[] args)
{
int numInstances = 3;
try {
// Initialise the ORB
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);
// Create the StockDispenser object
StockDispenserImpl dispenser = new StockDispenserImpl(args,"Stock Dispenser",numInstances);
// Export the new object
orb.connect(dispenser);
// Get the naming service
org.omg.CORBA.Object nameServiceObj = orb.resolve_initial_references("NameService");
if(nameServiceObj == null) {
System.err.println("nameServiceObj = null");
return;
}
org.omg.CosNaming.NamingContext nameService = org.omg.CosNaming.NamingContextHelper.narrow(nameServiceObj);
if(nameService == null) {
System.err.println("nameService = null");
return;
}
// bind the dispenser into the naming service
NameComponent[] dispenserName = {
new NameComponent("StockDispenser","Stock")
};
nameService.rebind(dispenserName,dispenser);
// Now wait forever for the current thread to die
Thread.currentThread().join();
} catch(Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,34 @@
The CORBA example is the most complicated of the examples. It
aims to show how to use JDBC & Java2's ORB to access PostgreSQL.
To compile:
Type "make corba" to build the example. This will create a new directory
stock which contains the stubs needed by the orb, and all required classes
under the example/corba directory.
To run:
NOTE: To run, you will need 3 shells on Win32 (under unix you can get away
with two shells):
1: Start the naming service
Unix: tnameserv -ORBInitialPort 1050 &
Win32: tnameserv -ORBInitialPort 1050
2: Start the StockServer
java example.corba.StockServer 3 jdbc:postgresql:dbase user passwd -ORBInitialPort 1050
Where:
3 Number of concurrent sessions to allow
dbase The database (including a hostname if required)
user The PostgreSQL user name
passwd The password
3: Using a fresh shell, run the client:
java example.corba.StockClient -ORBInitialPort 1050

View File

@ -0,0 +1,40 @@
// $Id: stock.idl,v 1.1 1999/01/25 21:22:04 scrappy Exp $
//
// This is our CORBA bindings for a very simple stock control
// system.
//
// $Id: stock.idl,v 1.1 1999/01/25 21:22:04 scrappy Exp $
//
// For some reason, idltojava on my setup doesn't like this to be
// in caps. It could be a problem with Win95 & Samba, but for now,
// this is in lowercase
module stock
{
exception StockException
{
string reason;
};
interface StockItem
{
void fetchItem(in long id) raises (StockException);
long newItem() raises (StockException);
string getDescription() raises (StockException);
long getAvailable() raises (StockException);
long getOrdered() raises (StockException);
boolean isItemValid() raises (StockException);
void addNewStock(in long amount) raises (StockException);
void removeStock(in long amount) raises (StockException);
void orderStock(in long amount) raises (StockException);
long getLastID() raises (StockException);
string getInstanceName();
};
interface StockDispenser
{
StockItem reserveItem() raises (StockException);
void releaseItem(in StockItem item) raises (StockException);
};
};

View File

@ -0,0 +1,27 @@
--
-- This creates the database for the stock example
-- $Id: stock.sql,v 1.1 1999/01/25 21:22:04 scrappy Exp $
--
drop table stock;
create table stock (
id int4,
avail int4,
ordered int4,
valid bool,
description text
);
create index stock_id on stock(id);
copy stock from stdin;
1 19 0 t Dell Latitude XPi P133 Laptop
2 3 2 t Iomega Zip Plus drive
3 2 0 f Iomega Ext/Par drive
4 0 4 t Iomega Ext USB drive
5 200 0 t Blank Unbranded CDR media
6 20 30 t Iomega Zip media 100Mb
\.
grant all on stock to public;
grant all on stock_id to public;

View File

@ -6,10 +6,15 @@ package postgresql.jdbc1;
// postgresql.jdbc2 package.
import java.lang.*;
import java.sql.*;
import java.util.*;
import postgresql.*;
// We explicitly import classes here as the original line:
//import java.sql.*;
// causes javac to get confused.
import java.sql.SQLException;
import java.sql.Types;
/**
* A ResultSetMetaData object can be used to find out about the types and
* properties of the columns in a ResultSet

View File

@ -789,9 +789,12 @@ public class ResultSet extends postgresql.ResultSet implements java.sql.ResultSe
// ** JDBC 2 Extensions **
public boolean absolute(int row) throws SQLException
public boolean absolute(int index) throws SQLException
{
throw postgresql.Driver.notImplemented();
if (index < 0 || index > rows.size())
return false;
this_row = (byte [][])rows.elementAt(index);
return true;
}
public void afterLast() throws SQLException
@ -816,7 +819,11 @@ public class ResultSet extends postgresql.ResultSet implements java.sql.ResultSe
public boolean first() throws SQLException
{
throw postgresql.Driver.notImplemented();
if (rows.size() <= 0)
return false;
current_row = 0;
this_row = (byte [][])rows.elementAt(current_row);
return true;
}
public Array getArray(String colName) throws SQLException
@ -941,7 +948,7 @@ public class ResultSet extends postgresql.ResultSet implements java.sql.ResultSe
public int getRow() throws SQLException
{
throw postgresql.Driver.notImplemented();
return current_row;
}
// This one needs some thought, as not all ResultSets come from a statement
@ -982,7 +989,11 @@ public class ResultSet extends postgresql.ResultSet implements java.sql.ResultSe
public boolean last() throws SQLException
{
throw postgresql.Driver.notImplemented();
if (rows.size() <= 0)
return false;
current_row = rows.size() - 1;
this_row = (byte [][])rows.elementAt(current_row);
return true;
}
public void moveToCurrentRow() throws SQLException
@ -997,7 +1008,10 @@ public class ResultSet extends postgresql.ResultSet implements java.sql.ResultSe
public boolean previous() throws SQLException
{
throw postgresql.Driver.notImplemented();
if (--current_row < 0)
return false;
this_row = (byte [][])rows.elementAt(current_row);
return true;
}
public void refreshRow() throws SQLException