diff --git a/src/interfaces/jdbc/CHANGELOG b/src/interfaces/jdbc/CHANGELOG index 2f3dfe2eb20..103c1bf6ff0 100644 --- a/src/interfaces/jdbc/CHANGELOG +++ b/src/interfaces/jdbc/CHANGELOG @@ -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) diff --git a/src/interfaces/jdbc/Makefile b/src/interfaces/jdbc/Makefile index 611687dc9a9..ab8abc96510 100644 --- a/src/interfaces/jdbc/Makefile +++ b/src/interfaces/jdbc/Makefile @@ -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 ####################################################################### diff --git a/src/interfaces/jdbc/example/corba/StockClient.java b/src/interfaces/jdbc/example/corba/StockClient.java new file mode 100644 index 00000000000..7613f886fc1 --- /dev/null +++ b/src/interfaces/jdbc/example/corba/StockClient.java @@ -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; + } +} diff --git a/src/interfaces/jdbc/example/corba/StockDB.java b/src/interfaces/jdbc/example/corba/StockDB.java new file mode 100644 index 00000000000..49ceb1434c3 --- /dev/null +++ b/src/interfaces/jdbc/example/corba/StockDB.java @@ -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"); + } + +} diff --git a/src/interfaces/jdbc/example/corba/StockDispenserImpl.java b/src/interfaces/jdbc/example/corba/StockDispenserImpl.java new file mode 100644 index 00000000000..2d961a6dc7b --- /dev/null +++ b/src/interfaces/jdbc/example/corba/StockDispenserImpl.java @@ -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 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