summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/interfaces/jdbc/example/ImageViewer.java902
-rw-r--r--src/interfaces/jdbc/example/Unicode.java494
-rw-r--r--src/interfaces/jdbc/example/basic.java376
-rw-r--r--src/interfaces/jdbc/example/blobtest.java448
-rw-r--r--src/interfaces/jdbc/example/corba/StockClient.java574
-rw-r--r--src/interfaces/jdbc/example/corba/StockDB.java203
-rw-r--r--src/interfaces/jdbc/example/corba/StockDispenserImpl.java145
-rw-r--r--src/interfaces/jdbc/example/corba/StockItemImpl.java327
-rw-r--r--src/interfaces/jdbc/example/corba/StockServer.java85
-rw-r--r--src/interfaces/jdbc/example/datestyle.java336
-rw-r--r--src/interfaces/jdbc/example/metadata.java536
-rw-r--r--src/interfaces/jdbc/example/psql.java449
-rw-r--r--src/interfaces/jdbc/example/threadsafe.java718
-rw-r--r--src/interfaces/jdbc/org/postgresql/Connection.java2185
-rw-r--r--src/interfaces/jdbc/org/postgresql/Field.java162
-rw-r--r--src/interfaces/jdbc/org/postgresql/PG_Stream.java629
-rw-r--r--src/interfaces/jdbc/org/postgresql/PostgresqlDataSource.java996
-rw-r--r--src/interfaces/jdbc/org/postgresql/ResultSet.java389
-rw-r--r--src/interfaces/jdbc/org/postgresql/Statement.java575
-rw-r--r--src/interfaces/jdbc/org/postgresql/core/BytePoolDim1.java154
-rw-r--r--src/interfaces/jdbc/org/postgresql/core/BytePoolDim2.java111
-rw-r--r--src/interfaces/jdbc/org/postgresql/core/Encoding.java358
-rw-r--r--src/interfaces/jdbc/org/postgresql/core/MemoryPool.java25
-rw-r--r--src/interfaces/jdbc/org/postgresql/core/ObjectPool.java79
-rw-r--r--src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java359
-rw-r--r--src/interfaces/jdbc/org/postgresql/core/SimpleObjectPool.java161
-rw-r--r--src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java523
-rw-r--r--src/interfaces/jdbc/org/postgresql/fastpath/FastpathArg.java163
-rw-r--r--src/interfaces/jdbc/org/postgresql/geometric/PGbox.java189
-rw-r--r--src/interfaces/jdbc/org/postgresql/geometric/PGcircle.java196
-rw-r--r--src/interfaces/jdbc/org/postgresql/geometric/PGline.java179
-rw-r--r--src/interfaces/jdbc/org/postgresql/geometric/PGlseg.java179
-rw-r--r--src/interfaces/jdbc/org/postgresql/geometric/PGpath.java275
-rw-r--r--src/interfaces/jdbc/org/postgresql/geometric/PGpoint.java306
-rw-r--r--src/interfaces/jdbc/org/postgresql/geometric/PGpolygon.java191
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc1/CallableStatement.java546
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc1/Connection.java344
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java5458
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc1/PreparedStatement.java561
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java1791
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc1/ResultSetMetaData.java883
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc1/Statement.java28
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/Array.java446
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/CallableStatement.java646
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java554
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java5746
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/PBatchUpdateException.java19
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java1054
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java2826
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/ResultSetMetaData.java901
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/Statement.java242
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/UpdateableResultSet.java440
-rw-r--r--src/interfaces/jdbc/org/postgresql/largeobject/BlobInputStream.java326
-rw-r--r--src/interfaces/jdbc/org/postgresql/largeobject/BlobOutputStream.java186
-rw-r--r--src/interfaces/jdbc/org/postgresql/largeobject/LargeObject.java495
-rw-r--r--src/interfaces/jdbc/org/postgresql/largeobject/LargeObjectManager.java291
-rw-r--r--src/interfaces/jdbc/org/postgresql/largeobject/PGblob.java84
-rw-r--r--src/interfaces/jdbc/org/postgresql/largeobject/PGclob.java77
-rw-r--r--src/interfaces/jdbc/org/postgresql/test/JDBC2Tests.java109
-rw-r--r--src/interfaces/jdbc/org/postgresql/test/jdbc2/ANTTest.java39
-rw-r--r--src/interfaces/jdbc/org/postgresql/test/jdbc2/BatchExecuteTest.java78
-rw-r--r--src/interfaces/jdbc/org/postgresql/test/jdbc2/BlobTest.java140
-rw-r--r--src/interfaces/jdbc/org/postgresql/test/jdbc2/ConnectionTest.java461
-rw-r--r--src/interfaces/jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java584
-rw-r--r--src/interfaces/jdbc/org/postgresql/test/jdbc2/DateTest.java50
-rw-r--r--src/interfaces/jdbc/org/postgresql/test/jdbc2/DriverTest.java114
-rw-r--r--src/interfaces/jdbc/org/postgresql/test/jdbc2/EncodingTest.java91
-rw-r--r--src/interfaces/jdbc/org/postgresql/test/jdbc2/JBuilderTest.java103
-rw-r--r--src/interfaces/jdbc/org/postgresql/test/jdbc2/MiscTest.java75
-rw-r--r--src/interfaces/jdbc/org/postgresql/test/jdbc2/TimeTest.java80
-rw-r--r--src/interfaces/jdbc/org/postgresql/test/jdbc2/TimestampTest.java62
-rw-r--r--src/interfaces/jdbc/org/postgresql/util/MessageTranslator.java48
-rw-r--r--src/interfaces/jdbc/org/postgresql/util/PGbytea.java160
-rw-r--r--src/interfaces/jdbc/org/postgresql/util/PGmoney.java178
-rw-r--r--src/interfaces/jdbc/org/postgresql/util/PGobject.java171
-rw-r--r--src/interfaces/jdbc/org/postgresql/util/PGtokenizer.java358
-rw-r--r--src/interfaces/jdbc/org/postgresql/util/PSQLException.java179
-rw-r--r--src/interfaces/jdbc/org/postgresql/util/Serialize.java686
-rw-r--r--src/interfaces/jdbc/org/postgresql/util/UnixCrypt.java1323
-rw-r--r--src/interfaces/jdbc/org/postgresql/xa/ClientConnection.java848
-rw-r--r--src/interfaces/jdbc/org/postgresql/xa/TwoPhaseConnection.java140
-rw-r--r--src/interfaces/jdbc/org/postgresql/xa/TxConnection.java204
-rw-r--r--src/interfaces/jdbc/org/postgresql/xa/XAConnectionImpl.java1616
-rw-r--r--src/interfaces/jdbc/org/postgresql/xa/XADataSourceImpl.java847
-rw-r--r--src/interfaces/jdbc/utils/CheckVersion.java118
85 files changed, 24211 insertions, 22572 deletions
diff --git a/src/interfaces/jdbc/example/ImageViewer.java b/src/interfaces/jdbc/example/ImageViewer.java
index 80581f79506..6097439bab3 100644
--- a/src/interfaces/jdbc/example/ImageViewer.java
+++ b/src/interfaces/jdbc/example/ImageViewer.java
@@ -33,432 +33,486 @@ import org.postgresql.largeobject.*;
public class ImageViewer implements ItemListener
{
- Connection db;
- Statement stat;
- LargeObjectManager lom;
- Frame frame;
- Label label; // Label used to display the current name
- List list; // The list of available images
- imageCanvas canvas; // Canvas used to display the image
- String currentImage; // The current images name
-
- // This is a simple component to display our image
- public class imageCanvas extends Canvas
- {
- // holds the image
- private Image image;
-
- // holds the background buffer
- private Image bkg;
-
- // the size of the buffer
- private Dimension size;
-
- public imageCanvas()
- {
- image=null;
- }
-
- public void setImage(Image img)
- {
- image=img;
- repaint();
- }
-
- // This defines our minimum size
- public Dimension getMinimumSize()
- {
- return new Dimension(400,400);
- }
-
- public Dimension getPreferedSize()
- {
- return getMinimumSize();
- }
-
- public void update(Graphics g)
- {
- paint(g);
- }
-
- /**
- * Paints the image, using double buffering to prevent screen flicker
- */
- public void paint(Graphics gr)
- {
- Dimension s = getSize();
-
- if(size==null || bkg==null || !s.equals(size)) {
- size = s;
- bkg = createImage(size.width,size.height);
- }
-
- // now set the background
- Graphics g = bkg.getGraphics();
- g.setColor(Color.gray);
- g.fillRect(0,0,s.width,s.height);
-
- // now paint the image over the background
- if(image!=null)
- g.drawImage(image,0,0,this);
-
- // dispose the graphics instance
- g.dispose();
-
- // paint the image onto the component
- gr.drawImage(bkg,0,0,this);
-
- }
-
- }
-
- public ImageViewer(Frame f,String url,String user,String password) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException
- {
- frame = f;
-
- MenuBar mb = new MenuBar();
- Menu m;
- MenuItem i;
-
- f.setMenuBar(mb);
- mb.add(m = new Menu("PostgreSQL"));
- m.add(i= new MenuItem("Initialise"));
- i.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- ImageViewer.this.init();
- }
- });
-
- m.add(i= new MenuItem("Exit"));
- ActionListener exitListener = new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- ImageViewer.this.close();
- }
- };
- m.addActionListener(exitListener);
-
- mb.add(m = new Menu("Image"));
- m.add(i= new MenuItem("Import"));
- ActionListener importListener = new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- ImageViewer.this.importImage();
- }
- };
- i.addActionListener(importListener);
-
- m.add(i= new MenuItem("Remove"));
- ActionListener removeListener = new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- ImageViewer.this.removeImage();
- }
- };
- i.addActionListener(removeListener);
-
- // To the north is a label used to display the current images name
- f.add("North",label = new Label());
-
- // We have a panel to the south of the frame containing the controls
- Panel p = new Panel();
- p.setLayout(new FlowLayout());
- Button b;
- p.add(b=new Button("Refresh List"));
- b.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- ImageViewer.this.refreshList();
- }
- });
- p.add(b=new Button("Import new image"));
- b.addActionListener(importListener);
- p.add(b=new Button("Remove image"));
- b.addActionListener(removeListener);
- p.add(b=new Button("Quit"));
- b.addActionListener(exitListener);
- f.add("South",p);
-
- // And a panel to the west containing the list of available images
- f.add("West",list=new List());
- list.addItemListener(this);
-
- // Finally the centre contains our image
- f.add("Center",canvas = new imageCanvas());
-
- // Load the driver
- Class.forName("org.postgresql.Driver");
-
- // Connect to database
- db = DriverManager.getConnection(url, user, password);
-
- // Create a statement
- stat = db.createStatement();
-
- // Also, get the LargeObjectManager for this connection
- lom = ((org.postgresql.Connection)db).getLargeObjectAPI();
-
- // Now refresh the image selection list
- refreshList();
- }
-
-
- /**
- * This method initialises the database by creating a table that contains
- * the image names, and Large Object OID's
- */
- public void init()
- {
- try {
- //db.setAutoCommit(true);
- stat.executeUpdate("create table images (imgname name,imgoid oid)");
- label.setText("Initialised database");
- db.commit();
- } catch(SQLException ex) {
- label.setText(ex.toString());
- }
-
- // This must run outside the previous try{} catch{} segment
- //try {
- //db.setAutoCommit(true);
- //} catch(SQLException ex) {
- //label.setText(ex.toString());
- //}
- }
-
- /**
- * This closes the connection, and ends the application
- */
- public void close()
- {
- try {
- db.close();
- } catch(SQLException ex) {
- System.err.println(ex.toString());
- }
- System.exit(0);
- }
-
- /**
- * This imports an image into the database, using a Thread to do this in the
- * background.
- */
- public void importImage()
- {
- FileDialog d = new FileDialog(frame,"Import Image",FileDialog.LOAD);
- d.setVisible(true);
- String name = d.getFile();
- String dir = d.getDirectory();
- d.dispose();
-
- // now start the true importer
- Thread t = new importer(db,name,dir);
- //t.setPriority(Thread.MAX_PRIORITY);
- t.start();
- }
-
- /**
- * This is an example of using a thread to import a file into a Large Object.
- * It uses the Large Object extension, to write blocks of the file to the
- * database.
- */
- class importer extends Thread
- {
- String name,dir;
- Connection db;
-
- public importer(Connection db,String name,String dir) {
- this.db = db;
- this.name = name;
- this.dir = dir;
- }
-
- public void run() {
-
- // Now the real import stuff
- if(name!=null && dir!=null) {
- Statement stat = null;
-
- try {
- // fetch the large object manager
- LargeObjectManager lom = ((org.postgresql.Connection)db).getLargeObjectAPI();
-
- db.setAutoCommit(false);
-
- // A temporary buffer - this can be as large as you like
- byte buf[] = new byte[2048];
-
- // Open the file
- FileInputStream fis = new FileInputStream(new File(dir,name));
-
- // Now create the large object
- int oid = lom.create();
- LargeObject blob = lom.open(oid);
-
- // Now copy the file into the object.
- //
- // Note: we dont use write(buf), as the last block is rarely the same
- // size as our buffer, so we have to use the amount read.
- int s,t=0;
- while((s=fis.read(buf,0,buf.length))>0) {
- t+=s;
- blob.write(buf,0,s);
- }
-
- // Close the object
- blob.close();
-
- // Now store the entry into the table
-
- // As we are a different thread to the other window, we must use
- // our own thread
- stat = db.createStatement();
- stat.executeUpdate("insert into images values ('"+name+"',"+oid+")");
- db.commit();
- db.setAutoCommit(false);
-
- // Finally refresh the names list, and display the current image
- ImageViewer.this.refreshList();
- ImageViewer.this.displayImage(name);
- } catch(Exception ex) {
- label.setText(ex.toString());
- } finally {
- // ensure the statement is closed after us
- try {
- if(stat != null)
- stat.close();
- } catch(SQLException se) {
- System.err.println("closing of Statement failed");
- }
+ Connection db;
+ Statement stat;
+ LargeObjectManager lom;
+ Frame frame;
+ Label label; // Label used to display the current name
+ List list; // The list of available images
+ imageCanvas canvas; // Canvas used to display the image
+ String currentImage; // The current images name
+
+ // This is a simple component to display our image
+ public class imageCanvas extends Canvas
+ {
+ // holds the image
+ private Image image;
+
+ // holds the background buffer
+ private Image bkg;
+
+ // the size of the buffer
+ private Dimension size;
+
+ public imageCanvas()
+ {
+ image = null;
+ }
+
+ public void setImage(Image img)
+ {
+ image = img;
+ repaint();
+ }
+
+ // This defines our minimum size
+ public Dimension getMinimumSize()
+ {
+ return new Dimension(400, 400);
+ }
+
+ public Dimension getPreferedSize()
+ {
+ return getMinimumSize();
+ }
+
+ public void update(Graphics g)
+ {
+ paint(g);
+ }
+
+ /**
+ * Paints the image, using double buffering to prevent screen flicker
+ */
+ public void paint(Graphics gr)
+ {
+ Dimension s = getSize();
+
+ if (size == null || bkg == null || !s.equals(size))
+ {
+ size = s;
+ bkg = createImage(size.width, size.height);
+ }
+
+ // now set the background
+ Graphics g = bkg.getGraphics();
+ g.setColor(Color.gray);
+ g.fillRect(0, 0, s.width, s.height);
+
+ // now paint the image over the background
+ if (image != null)
+ g.drawImage(image, 0, 0, this);
+
+ // dispose the graphics instance
+ g.dispose();
+
+ // paint the image onto the component
+ gr.drawImage(bkg, 0, 0, this);
+
+ }
+
+ }
+
+ public ImageViewer(Frame f, String url, String user, String password) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException
+ {
+ frame = f;
+
+ MenuBar mb = new MenuBar();
+ Menu m;
+ MenuItem i;
+
+ f.setMenuBar(mb);
+ mb.add(m = new Menu("PostgreSQL"));
+ m.add(i = new MenuItem("Initialise"));
+ i.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ ImageViewer.this.init();
+ }
+ }
+ );
+
+ m.add(i = new MenuItem("Exit"));
+ ActionListener exitListener = new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ ImageViewer.this.close();
+ }
+ };
+ m.addActionListener(exitListener);
+
+ mb.add(m = new Menu("Image"));
+ m.add(i = new MenuItem("Import"));
+ ActionListener importListener = new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ ImageViewer.this.importImage();
+ }
+ };
+ i.addActionListener(importListener);
+
+ m.add(i = new MenuItem("Remove"));
+ ActionListener removeListener = new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ ImageViewer.this.removeImage();
+ }
+ };
+ i.addActionListener(removeListener);
+
+ // To the north is a label used to display the current images name
+ f.add("North", label = new Label());
+
+ // We have a panel to the south of the frame containing the controls
+ Panel p = new Panel();
+ p.setLayout(new FlowLayout());
+ Button b;
+ p.add(b = new Button("Refresh List"));
+ b.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ ImageViewer.this.refreshList();
+ }
+ }
+ );
+ p.add(b = new Button("Import new image"));
+ b.addActionListener(importListener);
+ p.add(b = new Button("Remove image"));
+ b.addActionListener(removeListener);
+ p.add(b = new Button("Quit"));
+ b.addActionListener(exitListener);
+ f.add("South", p);
+
+ // And a panel to the west containing the list of available images
+ f.add("West", list = new List());
+ list.addItemListener(this);
+
+ // Finally the centre contains our image
+ f.add("Center", canvas = new imageCanvas());
+
+ // Load the driver
+ Class.forName("org.postgresql.Driver");
+
+ // Connect to database
+ db = DriverManager.getConnection(url, user, password);
+
+ // Create a statement
+ stat = db.createStatement();
+
+ // Also, get the LargeObjectManager for this connection
+ lom = ((org.postgresql.Connection)db).getLargeObjectAPI();
+
+ // Now refresh the image selection list
+ refreshList();
+ }
+
+
+ /**
+ * This method initialises the database by creating a table that contains
+ * the image names, and Large Object OID's
+ */
+ public void init()
+ {
+ try
+ {
+ //db.setAutoCommit(true);
+ stat.executeUpdate("create table images (imgname name,imgoid oid)");
+ label.setText("Initialised database");
+ db.commit();
+ }
+ catch (SQLException ex)
+ {
+ label.setText(ex.toString());
+ }
+
+ // This must run outside the previous try{} catch{} segment
+ //try {
+ //db.setAutoCommit(true);
+ //} catch(SQLException ex) {
+ //label.setText(ex.toString());
+ //}
}
- }
- }
- }
-
- /**
- * This refreshes the list of available images
- */
- public void refreshList()
- {
- try {
- // First, we'll run a query, retrieving all of the image names
- ResultSet rs = stat.executeQuery("select imgname from images order by imgname");
- if(rs!=null) {
- list.removeAll();
- while(rs.next())
- list.addItem(rs.getString(1));
- rs.close();
- }
- } catch(SQLException ex) {
- label.setText(ex.toString()+" Have you initialised the database?");
- }
- }
-
- /**
- * This removes an image from the database
- *
- * Note: With postgresql, this is the only way of deleting a large object
- * using Java.
- */
- public void removeImage()
- {
- try {
- //
- // Delete any large objects for the current name
- //
- // Note: We don't need to worry about being in a transaction
- // here, because we are not opening any blobs, only deleting
- // them
- //
- ResultSet rs = stat.executeQuery("select imgoid from images where imgname='"+currentImage+"'");
- if(rs!=null) {
- // Even though there should only be one image, we still have to
- // cycle through the ResultSet
- while(rs.next()) {
- lom.delete(rs.getInt(1));
+
+ /**
+ * This closes the connection, and ends the application
+ */
+ public void close()
+ {
+ try
+ {
+ db.close();
+ }
+ catch (SQLException ex)
+ {
+ System.err.println(ex.toString());
+ }
+ System.exit(0);
}
- }
- rs.close();
-
- // Finally delete any entries for that name
- stat.executeUpdate("delete from images where imgname='"+currentImage+"'");
-
- label.setText(currentImage+" deleted");
- currentImage=null;
- refreshList();
- } catch(SQLException ex) {
- label.setText(ex.toString());
- }
- }
-
- /**
- * This displays an image from the database.
- *
- * For images, this is the easiest method.
- */
- public void displayImage(String name)
- {
- try {
- //
- // Now as we are opening and reading a large object we must
- // turn on Transactions. This includes the ResultSet.getBytes()
- // method when it's used on a field of type oid!
- //
- db.setAutoCommit(false);
-
- ResultSet rs = stat.executeQuery("select imgoid from images where imgname='"+name+"'");
- if(rs!=null) {
- // Even though there should only be one image, we still have to
- // cycle through the ResultSet
- while(rs.next()) {
- canvas.setImage(canvas.getToolkit().createImage(rs.getBytes(1)));
- label.setText(currentImage = name);
+
+ /**
+ * This imports an image into the database, using a Thread to do this in the
+ * background.
+ */
+ public void importImage()
+ {
+ FileDialog d = new FileDialog(frame, "Import Image", FileDialog.LOAD);
+ d.setVisible(true);
+ String name = d.getFile();
+ String dir = d.getDirectory();
+ d.dispose();
+
+ // now start the true importer
+ Thread t = new importer(db, name, dir);
+ //t.setPriority(Thread.MAX_PRIORITY);
+ t.start();
}
- }
- rs.close();
- } catch(SQLException ex) {
- label.setText(ex.toString());
- } finally {
- try {
- db.setAutoCommit(true);
- } catch(SQLException ex2) {
+
+ /**
+ * This is an example of using a thread to import a file into a Large Object.
+ * It uses the Large Object extension, to write blocks of the file to the
+ * database.
+ */
+ class importer extends Thread
+ {
+ String name, dir;
+ Connection db;
+
+ public importer(Connection db, String name, String dir)
+ {
+ this.db = db;
+ this.name = name;
+ this.dir = dir;
+ }
+
+ public void run()
+ {
+
+ // Now the real import stuff
+ if (name != null && dir != null)
+ {
+ Statement stat = null;
+
+ try
+ {
+ // fetch the large object manager
+ LargeObjectManager lom = ((org.postgresql.Connection)db).getLargeObjectAPI();
+
+ db.setAutoCommit(false);
+
+ // A temporary buffer - this can be as large as you like
+ byte buf[] = new byte[2048];
+
+ // Open the file
+ FileInputStream fis = new FileInputStream(new File(dir, name));
+
+ // Now create the large object
+ int oid = lom.create();
+ LargeObject blob = lom.open(oid);
+
+ // Now copy the file into the object.
+ //
+ // Note: we dont use write(buf), as the last block is rarely the same
+ // size as our buffer, so we have to use the amount read.
+ int s, t = 0;
+ while ((s = fis.read(buf, 0, buf.length)) > 0)
+ {
+ t += s;
+ blob.write(buf, 0, s);
+ }
+
+ // Close the object
+ blob.close();
+
+ // Now store the entry into the table
+
+ // As we are a different thread to the other window, we must use
+ // our own thread
+ stat = db.createStatement();
+ stat.executeUpdate("insert into images values ('" + name + "'," + oid + ")");
+ db.commit();
+ db.setAutoCommit(false);
+
+ // Finally refresh the names list, and display the current image
+ ImageViewer.this.refreshList();
+ ImageViewer.this.displayImage(name);
+ }
+ catch (Exception ex)
+ {
+ label.setText(ex.toString());
+ }
+ finally
+ {
+ // ensure the statement is closed after us
+ try
+ {
+ if (stat != null)
+ stat.close();
+ }
+ catch (SQLException se)
+ {
+ System.err.println("closing of Statement failed");
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * This refreshes the list of available images
+ */
+ public void refreshList()
+ {
+ try
+ {
+ // First, we'll run a query, retrieving all of the image names
+ ResultSet rs = stat.executeQuery("select imgname from images order by imgname");
+ if (rs != null)
+ {
+ list.removeAll();
+ while (rs.next())
+ list.addItem(rs.getString(1));
+ rs.close();
+ }
+ }
+ catch (SQLException ex)
+ {
+ label.setText(ex.toString() + " Have you initialised the database?");
+ }
+ }
+
+ /**
+ * This removes an image from the database
+ *
+ * Note: With postgresql, this is the only way of deleting a large object
+ * using Java.
+ */
+ public void removeImage()
+ {
+ try
+ {
+ //
+ // Delete any large objects for the current name
+ //
+ // Note: We don't need to worry about being in a transaction
+ // here, because we are not opening any blobs, only deleting
+ // them
+ //
+ ResultSet rs = stat.executeQuery("select imgoid from images where imgname='" + currentImage + "'");
+ if (rs != null)
+ {
+ // Even though there should only be one image, we still have to
+ // cycle through the ResultSet
+ while (rs.next())
+ {
+ lom.delete(rs.getInt(1));
+ }
+ }
+ rs.close();
+
+ // Finally delete any entries for that name
+ stat.executeUpdate("delete from images where imgname='" + currentImage + "'");
+
+ label.setText(currentImage + " deleted");
+ currentImage = null;
+ refreshList();
+ }
+ catch (SQLException ex)
+ {
+ label.setText(ex.toString());
+ }
+ }
+
+ /**
+ * This displays an image from the database.
+ *
+ * For images, this is the easiest method.
+ */
+ public void displayImage(String name)
+ {
+ try
+ {
+ //
+ // Now as we are opening and reading a large object we must
+ // turn on Transactions. This includes the ResultSet.getBytes()
+ // method when it's used on a field of type oid!
+ //
+ db.setAutoCommit(false);
+
+ ResultSet rs = stat.executeQuery("select imgoid from images where imgname='" + name + "'");
+ if (rs != null)
+ {
+ // Even though there should only be one image, we still have to
+ // cycle through the ResultSet
+ while (rs.next())
+ {
+ canvas.setImage(canvas.getToolkit().createImage(rs.getBytes(1)));
+ label.setText(currentImage = name);
+ }
+ }
+ rs.close();
+ }
+ catch (SQLException ex)
+ {
+ label.setText(ex.toString());
+ }
+ finally
+ {
+ try
+ {
+ db.setAutoCommit(true);
+ }
+ catch (SQLException ex2)
+ {}
+ }
+ }
+
+ public void itemStateChanged(ItemEvent e)
+ {
+ displayImage(list.getItem(((Integer)e.getItem()).intValue()));
+ }
+
+ /**
+ * This is the command line instructions
+ */
+ public static void instructions()
+ {
+ System.err.println("java example.ImageViewer jdbc-url user password");
+ System.err.println("\nExamples:\n");
+ System.err.println("java -Djdbc.driver=org.postgresql.Driver example.ImageViewer jdbc:postgresql:test postgres password\n");
+
+ System.err.println("This example tests the binary large object api of the driver.\nBasically, it will allow you to store and view images held in the database.");
+ System.err.println("Note: If you are running this for the first time on a particular database,\nyou have to select \"Initialise\" in the \"PostgreSQL\" menu.\nThis will create a table used to store image names.");
+ }
+
+ /**
+ * This is the application entry point
+ */
+ public static void main(String args[])
+ {
+ if (args.length != 3)
+ {
+ instructions();
+ System.exit(1);
+ }
+
+ try
+ {
+ Frame frame = new Frame("PostgreSQL ImageViewer v7.0 rev 1");
+ frame.setLayout(new BorderLayout());
+ ImageViewer viewer = new ImageViewer(frame, args[0], args[1], args[2]);
+ frame.pack();
+ frame.setLocation(0, 50);
+ frame.setVisible(true);
+ }
+ catch (Exception ex)
+ {
+ System.err.println("Exception caught.\n" + ex);
+ ex.printStackTrace();
+ }
}
- }
- }
-
- public void itemStateChanged(ItemEvent e) {
- displayImage(list.getItem(((Integer)e.getItem()).intValue()));
- }
-
- /**
- * This is the command line instructions
- */
- public static void instructions()
- {
- System.err.println("java example.ImageViewer jdbc-url user password");
- System.err.println("\nExamples:\n");
- System.err.println("java -Djdbc.driver=org.postgresql.Driver example.ImageViewer jdbc:postgresql:test postgres password\n");
-
- System.err.println("This example tests the binary large object api of the driver.\nBasically, it will allow you to store and view images held in the database.");
- System.err.println("Note: If you are running this for the first time on a particular database,\nyou have to select \"Initialise\" in the \"PostgreSQL\" menu.\nThis will create a table used to store image names.");
- }
-
- /**
- * This is the application entry point
- */
- public static void main(String args[])
- {
- if(args.length!=3) {
- instructions();
- System.exit(1);
- }
-
- try {
- Frame frame = new Frame("PostgreSQL ImageViewer v7.0 rev 1");
- frame.setLayout(new BorderLayout());
- ImageViewer viewer = new ImageViewer(frame,args[0],args[1],args[2]);
- frame.pack();
- frame.setLocation(0,50);
- frame.setVisible(true);
- } catch(Exception ex) {
- System.err.println("Exception caught.\n"+ex);
- ex.printStackTrace();
- }
- }
}
diff --git a/src/interfaces/jdbc/example/Unicode.java b/src/interfaces/jdbc/example/Unicode.java
index 64d7ce8c89e..f5e56522f50 100644
--- a/src/interfaces/jdbc/example/Unicode.java
+++ b/src/interfaces/jdbc/example/Unicode.java
@@ -5,236 +5,274 @@ import java.sql.*;
import java.util.*;
/**
- * Test inserting and extracting Unicode-encoded strings.
+ * Test inserting and extracting Unicode-encoded strings.
*
- * Synopsis:
- * example.Unicode <url> <user> <password>
- * where <url> must specify an existing database to which <user> and
- * <password> give access and which has UNICODE as its encoding.
- * (To create a database with UNICODE encoding, you need to compile
- * postgres with "--enable-multibyte" and run createdb with the
- * flag "-E UNICODE".)
+ * Synopsis:
+ * example.Unicode <url> <user> <password>
+ * where <url> must specify an existing database to which <user> and
+ * <password> give access and which has UNICODE as its encoding.
+ * (To create a database with UNICODE encoding, you need to compile
+ * postgres with "--enable-multibyte" and run createdb with the
+ * flag "-E UNICODE".)
*
- * This test only produces output on error.
+ * This test only produces output on error.
*
- * @author William Webber <william@live.com.au>
+ * @author William Webber <william@live.com.au>
*/
-public class Unicode {
-
- /**
- * The url for the database to connect to.
- */
- private String url;
-
- /**
- * The user to connect as.
- */
- private String user;
-
- /**
- * The password to connect with.
- */
- private String password;
-
- private static void usage() {
- log("usage: example.Unicode <url> <user> <password>");
- }
-
- private static void log(String message) {
- System.err.println(message);
- }
-
- private static void log(String message, Exception e) {
- System.err.println(message);
- e.printStackTrace();
- }
-
-
- public Unicode(String url, String user, String password) {
- this.url = url;
- this.user = user;
- this.password = password;
- }
-
- /**
- * Establish and return a connection to the database.
- */
- private Connection getConnection() throws SQLException,
- ClassNotFoundException {
- Class.forName("org.postgresql.Driver");
- Properties info = new Properties();
- info.put("user", user);
- info.put("password", password);
- info.put("charSet", "utf-8");
- return DriverManager.getConnection(url, info);
- }
-
- /**
- * Get string representing a block of 256 consecutive unicode characters.
- * We exclude the null character, "'", and "\".
- */
- private String getSqlSafeUnicodeBlock(int blockNum) {
- if (blockNum < 0 || blockNum > 255)
- throw new IllegalArgumentException("blockNum must be from 0 to "
- + "255: " + blockNum);
- StringBuffer sb = new StringBuffer(256);
- int blockFirst = blockNum * 256;
- int blockLast = blockFirst + 256;
- for (int i = blockFirst; i < blockLast; i++) {
- char c = (char) i;
- if (c == '\0' || c == '\'' || c == '\\')
- continue;
- sb.append(c);
- }
- return sb.toString();
- }
-
- /**
- * Is the block a block of valid unicode values.
- * d800 to db7f is the "unassigned high surrogate" range.
- * db80 to dbff is the "private use" range.
- * These should not be used in actual Unicode strings;
- * at least, jdk1.2 will not convert them to utf-8.
- */
- private boolean isValidUnicodeBlock(int blockNum) {
- if (blockNum >= 0xd8 && blockNum <= 0xdb)
- return false;
- else
- return true;
- }
-
- /**
- * Report incorrect block retrieval.
- */
- private void reportRetrievalError(int blockNum, String block,
- String retrieved) {
- String message = "Block " + blockNum + " returned incorrectly: ";
- int i = 0;
- for (i = 0; i < block.length(); i++) {
- if (i >= retrieved.length()) {
- message += "too short";
- break;
- } else if (retrieved.charAt(i) != block.charAt(i)) {
- message +=
- "first changed character at position " + i + ", sent as 0x"
- + Integer.toHexString((int) block.charAt(i))
- + ", retrieved as 0x"
- + Integer.toHexString ((int) retrieved.charAt(i));
- break;
- }
- }
- if (i >= block.length())
- message += "too long";
- log(message);
- }
-
- /**
- * Do the testing.
- */
- public void runTest() {
- Connection connection = null;
- Statement statement = null;
- int blockNum = 0;
- final int CREATE = 0;
- final int INSERT = 1;
- final int SELECT = 2;
- final int LIKE = 3;
- int mode = CREATE;
- try {
- connection = getConnection();
- statement = connection.createStatement();
- statement.executeUpdate("CREATE TABLE test_unicode "
- + "( blockNum INT PRIMARY KEY, "
- + "block TEXT );");
- mode = INSERT;
- for (blockNum = 0; blockNum < 256; blockNum++) {
- if (isValidUnicodeBlock(blockNum)) {
- String block = getSqlSafeUnicodeBlock(blockNum);
- statement.executeUpdate
- ("INSERT INTO test_unicode VALUES ( " + blockNum
- + ", '" + block + "');");
- }
- }
- mode = SELECT;
- for (blockNum = 0; blockNum < 256; blockNum++) {
- if (isValidUnicodeBlock(blockNum)) {
- String block = getSqlSafeUnicodeBlock(blockNum);
- ResultSet rs = statement.executeQuery
- ("SELECT block FROM test_unicode WHERE blockNum = "
- + blockNum + ";");
- if (!rs.next())
- log("Could not retrieve block " + blockNum);
- else {
- String retrieved = rs.getString(1);
- if (!retrieved.equals(block)) {
- reportRetrievalError(blockNum, block, retrieved);
- }
- }
- }
- }
- mode = LIKE;
- for (blockNum = 0; blockNum < 256; blockNum++) {
- if (isValidUnicodeBlock(blockNum)) {
- String block = getSqlSafeUnicodeBlock(blockNum);
- String likeString = "%" +
- block.substring(2, block.length() - 3) + "%" ;
- ResultSet rs = statement.executeQuery
- ("SELECT blockNum FROM test_unicode WHERE block LIKE '"
- + likeString + "';");
- if (!rs.next())
- log("Could get block " + blockNum + " using LIKE");
- }
- }
- } catch (SQLException sqle) {
- switch (mode) {
- case CREATE:
- log("Exception creating database", sqle);
- break;
- case INSERT:
- log("Exception inserting block " + blockNum, sqle);
- break;
- case SELECT:
- log("Exception selecting block " + blockNum, sqle);
- break;
- case LIKE:
- log("Exception doing LIKE on block " + blockNum, sqle);
- break;
- default:
- log("Exception", sqle);
- break;
- }
- } catch (ClassNotFoundException cnfe) {
- log("Unable to load driver", cnfe);
- return;
- }
- try {
- if (statement != null)
- statement.close();
- if (connection != null)
- connection.close();
- } catch (SQLException sqle) {
- log("Exception closing connections", sqle);
- }
- if (mode > CREATE) {
- // If the backend gets what it regards as garbage on a connection,
- // that connection may become unusable. To be safe, we create
- // a fresh connection to delete the table.
- try {
- connection = getConnection();
- statement = connection.createStatement();
- statement.executeUpdate("DROP TABLE test_unicode;");
- } catch (Exception sqle) {
- log("*** ERROR: unable to delete test table "
- + "test_unicode; must be deleted manually", sqle);
- }
- }
- }
-
- public static void main(String [] args) {
- if (args.length != 3) {
- usage();
- System.exit(1);
- }
- new Unicode(args[0], args[1], args[2]).runTest();
- }
+public class Unicode
+{
+
+ /**
+ * The url for the database to connect to.
+ */
+ private String url;
+
+ /**
+ * The user to connect as.
+ */
+ private String user;
+
+ /**
+ * The password to connect with.
+ */
+ private String password;
+
+ private static void usage()
+ {
+ log("usage: example.Unicode <url> <user> <password>");
+ }
+
+ private static void log(String message)
+ {
+ System.err.println(message);
+ }
+
+ private static void log(String message, Exception e)
+ {
+ System.err.println(message);
+ e.printStackTrace();
+ }
+
+
+ public Unicode(String url, String user, String password)
+ {
+ this.url = url;
+ this.user = user;
+ this.password = password;
+ }
+
+ /**
+ * Establish and return a connection to the database.
+ */
+ private Connection getConnection() throws SQLException,
+ ClassNotFoundException
+ {
+ Class.forName("org.postgresql.Driver");
+ Properties info = new Properties();
+ info.put("user", user);
+ info.put("password", password);
+ info.put("charSet", "utf-8");
+ return DriverManager.getConnection(url, info);
+ }
+
+ /**
+ * Get string representing a block of 256 consecutive unicode characters.
+ * We exclude the null character, "'", and "\".
+ */
+ private String getSqlSafeUnicodeBlock(int blockNum)
+ {
+ if (blockNum < 0 || blockNum > 255)
+ throw new IllegalArgumentException("blockNum must be from 0 to "
+ + "255: " + blockNum);
+ StringBuffer sb = new StringBuffer(256);
+ int blockFirst = blockNum * 256;
+ int blockLast = blockFirst + 256;
+ for (int i = blockFirst; i < blockLast; i++)
+ {
+ char c = (char) i;
+ if (c == '\0' || c == '\'' || c == '\\')
+ continue;
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Is the block a block of valid unicode values.
+ * d800 to db7f is the "unassigned high surrogate" range.
+ * db80 to dbff is the "private use" range.
+ * These should not be used in actual Unicode strings;
+ * at least, jdk1.2 will not convert them to utf-8.
+ */
+ private boolean isValidUnicodeBlock(int blockNum)
+ {
+ if (blockNum >= 0xd8 && blockNum <= 0xdb)
+ return false;
+ else
+ return true;
+ }
+
+ /**
+ * Report incorrect block retrieval.
+ */
+ private void reportRetrievalError(int blockNum, String block,
+ String retrieved)
+ {
+ String message = "Block " + blockNum + " returned incorrectly: ";
+ int i = 0;
+ for (i = 0; i < block.length(); i++)
+ {
+ if (i >= retrieved.length())
+ {
+ message += "too short";
+ break;
+ }
+ else if (retrieved.charAt(i) != block.charAt(i))
+ {
+ message +=
+ "first changed character at position " + i + ", sent as 0x"
+ + Integer.toHexString((int) block.charAt(i))
+ + ", retrieved as 0x"
+ + Integer.toHexString ((int) retrieved.charAt(i));
+ break;
+ }
+ }
+ if (i >= block.length())
+ message += "too long";
+ log(message);
+ }
+
+ /**
+ * Do the testing.
+ */
+ public void runTest()
+ {
+ Connection connection = null;
+ Statement statement = null;
+ int blockNum = 0;
+ final int CREATE = 0;
+ final int INSERT = 1;
+ final int SELECT = 2;
+ final int LIKE = 3;
+ int mode = CREATE;
+ try
+ {
+ connection = getConnection();
+ statement = connection.createStatement();
+ statement.executeUpdate("CREATE TABLE test_unicode "
+ + "( blockNum INT PRIMARY KEY, "
+ + "block TEXT );");
+ mode = INSERT;
+ for (blockNum = 0; blockNum < 256; blockNum++)
+ {
+ if (isValidUnicodeBlock(blockNum))
+ {
+ String block = getSqlSafeUnicodeBlock(blockNum);
+ statement.executeUpdate
+ ("INSERT INTO test_unicode VALUES ( " + blockNum
+ + ", '" + block + "');");
+ }
+ }
+ mode = SELECT;
+ for (blockNum = 0; blockNum < 256; blockNum++)
+ {
+ if (isValidUnicodeBlock(blockNum))
+ {
+ String block = getSqlSafeUnicodeBlock(blockNum);
+ ResultSet rs = statement.executeQuery
+ ("SELECT block FROM test_unicode WHERE blockNum = "
+ + blockNum + ";");
+ if (!rs.next())
+ log("Could not retrieve block " + blockNum);
+ else
+ {
+ String retrieved = rs.getString(1);
+ if (!retrieved.equals(block))
+ {
+ reportRetrievalError(blockNum, block, retrieved);
+ }
+ }
+ }
+ }
+ mode = LIKE;
+ for (blockNum = 0; blockNum < 256; blockNum++)
+ {
+ if (isValidUnicodeBlock(blockNum))
+ {
+ String block = getSqlSafeUnicodeBlock(blockNum);
+ String likeString = "%" +
+ block.substring(2, block.length() - 3) + "%" ;
+ ResultSet rs = statement.executeQuery
+ ("SELECT blockNum FROM test_unicode WHERE block LIKE '"
+ + likeString + "';");
+ if (!rs.next())
+ log("Could get block " + blockNum + " using LIKE");
+ }
+ }
+ }
+ catch (SQLException sqle)
+ {
+ switch (mode)
+ {
+ case CREATE:
+ log("Exception creating database", sqle);
+ break;
+ case INSERT:
+ log("Exception inserting block " + blockNum, sqle);
+ break;
+ case SELECT:
+ log("Exception selecting block " + blockNum, sqle);
+ break;
+ case LIKE:
+ log("Exception doing LIKE on block " + blockNum, sqle);
+ break;
+ default:
+ log("Exception", sqle);
+ break;
+ }
+ }
+ catch (ClassNotFoundException cnfe)
+ {
+ log("Unable to load driver", cnfe);
+ return ;
+ }
+ try
+ {
+ if (statement != null)
+ statement.close();
+ if (connection != null)
+ connection.close();
+ }
+ catch (SQLException sqle)
+ {
+ log("Exception closing connections", sqle);
+ }
+ if (mode > CREATE)
+ {
+ // If the backend gets what it regards as garbage on a connection,
+ // that connection may become unusable. To be safe, we create
+ // a fresh connection to delete the table.
+ try
+ {
+ connection = getConnection();
+ statement = connection.createStatement();
+ statement.executeUpdate("DROP TABLE test_unicode;");
+ }
+ catch (Exception sqle)
+ {
+ log("*** ERROR: unable to delete test table "
+ + "test_unicode; must be deleted manually", sqle);
+ }
+ }
+ }
+
+ public static void main(String [] args)
+ {
+ if (args.length != 3)
+ {
+ usage();
+ System.exit(1);
+ }
+ new Unicode(args[0], args[1], args[2]).runTest();
+ }
}
diff --git a/src/interfaces/jdbc/example/basic.java b/src/interfaces/jdbc/example/basic.java
index 2c989b4c89a..8dd7d7baf75 100644
--- a/src/interfaces/jdbc/example/basic.java
+++ b/src/interfaces/jdbc/example/basic.java
@@ -6,7 +6,7 @@ import java.text.*;
/**
*
- * $Id: basic.java,v 1.7 2001/01/31 09:23:45 peter Exp $
+ * $Id: basic.java,v 1.8 2001/10/25 05:59:58 momjian Exp $
*
* This example tests the basic components of the JDBC driver, and shows
* how even the simplest of queries can be implemented.
@@ -20,184 +20,198 @@ import java.text.*;
public class basic
{
- Connection db; // The connection to the database
- Statement st; // Our statement to run queries with
-
- public basic(String args[]) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException
- {
- String url = args[0];
- String usr = args[1];
- String pwd = args[2];
-
- // Load the driver
- Class.forName("org.postgresql.Driver");
-
- // Connect to database
- System.out.println("Connecting to Database URL = " + url);
- db = DriverManager.getConnection(url, usr, pwd);
-
- System.out.println("Connected...Now creating a statement");
- st = db.createStatement();
-
- // Clean up the database (in case we failed earlier) then initialise
- cleanup();
-
- // Now run tests using JDBC methods
- doexample();
-
- // Clean up the database
- cleanup();
-
- // Finally close the database
- System.out.println("Now closing the connection");
- st.close();
- db.close();
-
- //throw postgresql.Driver.notImplemented();
- }
-
- /**
- * This drops the table (if it existed). No errors are reported.
- */
- public void cleanup()
- {
- try {
- st.executeUpdate("drop table basic");
- } catch(Exception ex) {
- // We ignore any errors here
- }
- }
-
- /**
- * This performs the example
- */
- public void doexample() throws SQLException
- {
- System.out.println("\nRunning tests:");
-
- // First we need a table to store data in
- st.executeUpdate("create table basic (a int2, b int2)");
-
- // Now insert some data, using the Statement
- st.executeUpdate("insert into basic values (1,1)");
- st.executeUpdate("insert into basic values (2,1)");
- st.executeUpdate("insert into basic values (3,1)");
-
- // This shows how to get the oid of a just inserted row
- // updated for 7.1
- st.executeUpdate("insert into basic values (4,1)");
- int insertedOID = ((org.postgresql.Statement)st).getInsertedOID();
- System.out.println("Inserted row with oid "+insertedOID);
-
- // Now change the value of b from 1 to 8
- st.executeUpdate("update basic set b=8");
- System.out.println("Updated "+st.getUpdateCount()+" rows");
-
- // Now delete 2 rows
- st.executeUpdate("delete from basic where a<3");
- System.out.println("deleted "+st.getUpdateCount()+" rows");
-
- // For large inserts, a PreparedStatement is more efficient, because it
- // supports the idea of precompiling the SQL statement, and to store
- // directly, a Java object into any column. PostgreSQL doesnt support
- // precompiling, but does support setting a column to the value of a
- // Java object (like Date, String, etc).
- //
- // Also, this is the only way of writing dates in a datestyle independent
- // manner. (DateStyles are PostgreSQL's way of handling different methods
- // of representing dates in the Date data type.)
- PreparedStatement ps = db.prepareStatement("insert into basic values (?,?)");
- for(int i=2;i<5;i++) {
- ps.setInt(1,4); // "column a" = 5
- ps.setInt(2,i); // "column b" = i
- ps.executeUpdate(); // executeUpdate because insert returns no data
- }
- ps.close(); // Always close when we are done with it
-
- // Finally perform a query on the table
- System.out.println("performing a query");
- ResultSet rs = st.executeQuery("select a, b from basic");
- if(rs!=null) {
- // Now we run through the result set, printing out the result.
- // Note, we must call .next() before attempting to read any results
- while(rs.next()) {
- int a = rs.getInt("a"); // This shows how to get the value by name
- int b = rs.getInt(2); // This shows how to get the value by column
- System.out.println(" a="+a+" b="+b);
- }
- rs.close(); // again, you must close the result when done
- }
-
- // Now run the query again, showing a more efficient way of getting the
- // result if you don't know what column number a value is in
- System.out.println("performing another query");
- rs = st.executeQuery("select * from basic where b>1");
- if(rs!=null) {
- // First find out the column numbers.
- //
- // It's best to do this here, as calling the methods with the column
- // numbers actually performs this call each time they are called. This
- // really speeds things up on large queries.
- //
- int col_a = rs.findColumn("a");
- int col_b = rs.findColumn("b");
-
- // Now we run through the result set, printing out the result.
- // Again, we must call .next() before attempting to read any results
- while(rs.next()) {
- int a = rs.getInt(col_a); // This shows how to get the value by name
- int b = rs.getInt(col_b); // This shows how to get the value by column
- System.out.println(" a="+a+" b="+b);
- }
- rs.close(); // again, you must close the result when done
- }
-
- // Now test maxrows by setting it to 3 rows
- st.setMaxRows(3);
- System.out.println("performing a query limited to "+st.getMaxRows());
- rs = st.executeQuery("select a, b from basic");
- while(rs.next()) {
- int a = rs.getInt("a"); // This shows how to get the value by name
- int b = rs.getInt(2); // This shows how to get the value by column
- System.out.println(" a="+a+" b="+b);
- }
- rs.close(); // again, you must close the result when done
-
- // The last thing to do is to drop the table. This is done in the
- // cleanup() method.
- }
-
- /**
- * Display some instructions on how to run the example
- */
- public static void instructions()
- {
- System.out.println("\nThis example tests the basic components of the JDBC driver, demonstrating\nhow to build simple queries in java.\n");
- System.out.println("Useage:\n java example.basic jdbc:postgresql:database user password [debug]\n\nThe debug field can be anything. It's presence will enable DriverManager's\ndebug trace. Unless you want to see screens of items, don't put anything in\nhere.");
- System.exit(1);
- }
-
- /**
- * This little lot starts the test
- */
- public static void main(String args[])
- {
- System.out.println("PostgreSQL basic test v6.3 rev 1\n");
-
- if(args.length<3)
- instructions();
-
- // This line outputs debug information to stderr. To enable this, simply
- // add an extra parameter to the command line
- if(args.length>3)
- DriverManager.setLogStream(System.err);
-
- // Now run the tests
- try {
- basic test = new basic(args);
- } catch(Exception ex) {
- System.err.println("Exception caught.\n"+ex);
- ex.printStackTrace();
- }
- }
+ Connection db; // The connection to the database
+ Statement st; // Our statement to run queries with
+
+ public basic(String args[]) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException
+ {
+ String url = args[0];
+ String usr = args[1];
+ String pwd = args[2];
+
+ // Load the driver
+ Class.forName("org.postgresql.Driver");
+
+ // Connect to database
+ System.out.println("Connecting to Database URL = " + url);
+ db = DriverManager.getConnection(url, usr, pwd);
+
+ System.out.println("Connected...Now creating a statement");
+ st = db.createStatement();
+
+ // Clean up the database (in case we failed earlier) then initialise
+ cleanup();
+
+ // Now run tests using JDBC methods
+ doexample();
+
+ // Clean up the database
+ cleanup();
+
+ // Finally close the database
+ System.out.println("Now closing the connection");
+ st.close();
+ db.close();
+
+ //throw postgresql.Driver.notImplemented();
+ }
+
+ /**
+ * This drops the table (if it existed). No errors are reported.
+ */
+ public void cleanup()
+ {
+ try
+ {
+ st.executeUpdate("drop table basic");
+ }
+ catch (Exception ex)
+ {
+ // We ignore any errors here
+ }
+ }
+
+ /**
+ * This performs the example
+ */
+ public void doexample() throws SQLException
+ {
+ System.out.println("\nRunning tests:");
+
+ // First we need a table to store data in
+ st.executeUpdate("create table basic (a int2, b int2)");
+
+ // Now insert some data, using the Statement
+ st.executeUpdate("insert into basic values (1,1)");
+ st.executeUpdate("insert into basic values (2,1)");
+ st.executeUpdate("insert into basic values (3,1)");
+
+ // This shows how to get the oid of a just inserted row
+ // updated for 7.1
+ st.executeUpdate("insert into basic values (4,1)");
+ int insertedOID = ((org.postgresql.Statement)st).getInsertedOID();
+ System.out.println("Inserted row with oid " + insertedOID);
+
+ // Now change the value of b from 1 to 8
+ st.executeUpdate("update basic set b=8");
+ System.out.println("Updated " + st.getUpdateCount() + " rows");
+
+ // Now delete 2 rows
+ st.executeUpdate("delete from basic where a<3");
+ System.out.println("deleted " + st.getUpdateCount() + " rows");
+
+ // For large inserts, a PreparedStatement is more efficient, because it
+ // supports the idea of precompiling the SQL statement, and to store
+ // directly, a Java object into any column. PostgreSQL doesnt support
+ // precompiling, but does support setting a column to the value of a
+ // Java object (like Date, String, etc).
+ //
+ // Also, this is the only way of writing dates in a datestyle independent
+ // manner. (DateStyles are PostgreSQL's way of handling different methods
+ // of representing dates in the Date data type.)
+ PreparedStatement ps = db.prepareStatement("insert into basic values (?,?)");
+ for (int i = 2;i < 5;i++)
+ {
+ ps.setInt(1, 4); // "column a" = 5
+ ps.setInt(2, i); // "column b" = i
+ ps.executeUpdate(); // executeUpdate because insert returns no data
+ }
+ ps.close(); // Always close when we are done with it
+
+ // Finally perform a query on the table
+ System.out.println("performing a query");
+ ResultSet rs = st.executeQuery("select a, b from basic");
+ if (rs != null)
+ {
+ // Now we run through the result set, printing out the result.
+ // Note, we must call .next() before attempting to read any results
+ while (rs.next())
+ {
+ int a = rs.getInt("a"); // This shows how to get the value by name
+ int b = rs.getInt(2); // This shows how to get the value by column
+ System.out.println(" a=" + a + " b=" + b);
+ }
+ rs.close(); // again, you must close the result when done
+ }
+
+ // Now run the query again, showing a more efficient way of getting the
+ // result if you don't know what column number a value is in
+
+ System.out.println("performing another query");
+ rs = st.executeQuery("select * from basic where b>1");
+ if (rs != null)
+ {
+ // First find out the column numbers.
+ //
+ // It's best to do this here, as calling the methods with the column
+ // numbers actually performs this call each time they are called. This
+ // really speeds things up on large queries.
+ //
+ int col_a = rs.findColumn("a");
+ int col_b = rs.findColumn("b");
+
+ // Now we run through the result set, printing out the result.
+ // Again, we must call .next() before attempting to read any results
+ while (rs.next())
+ {
+ int a = rs.getInt(col_a); // This shows how to get the value by name
+ int b = rs.getInt(col_b); // This shows how to get the value by column
+ System.out.println(" a=" + a + " b=" + b);
+ }
+ rs.close(); // again, you must close the result when done
+ }
+
+ // Now test maxrows by setting it to 3 rows
+
+ st.setMaxRows(3);
+ System.out.println("performing a query limited to " + st.getMaxRows());
+ rs = st.executeQuery("select a, b from basic");
+ while (rs.next())
+ {
+ int a = rs.getInt("a"); // This shows how to get the value by name
+ int b = rs.getInt(2); // This shows how to get the value by column
+ System.out.println(" a=" + a + " b=" + b);
+ }
+ rs.close(); // again, you must close the result when done
+
+ // The last thing to do is to drop the table. This is done in the
+ // cleanup() method.
+ }
+
+ /**
+ * Display some instructions on how to run the example
+ */
+ public static void instructions()
+ {
+ System.out.println("\nThis example tests the basic components of the JDBC driver, demonstrating\nhow to build simple queries in java.\n");
+ System.out.println("Useage:\n java example.basic jdbc:postgresql:database user password [debug]\n\nThe debug field can be anything. It's presence will enable DriverManager's\ndebug trace. Unless you want to see screens of items, don't put anything in\nhere.");
+ System.exit(1);
+ }
+
+ /**
+ * This little lot starts the test
+ */
+ public static void main(String args[])
+ {
+ System.out.println("PostgreSQL basic test v6.3 rev 1\n");
+
+ if (args.length < 3)
+ instructions();
+
+ // This line outputs debug information to stderr. To enable this, simply
+ // add an extra parameter to the command line
+ if (args.length > 3)
+ DriverManager.setLogStream(System.err);
+
+ // Now run the tests
+ try
+ {
+ basic test = new basic(args);
+ }
+ catch (Exception ex)
+ {
+ System.err.println("Exception caught.\n" + ex);
+ ex.printStackTrace();
+ }
+ }
}
diff --git a/src/interfaces/jdbc/example/blobtest.java b/src/interfaces/jdbc/example/blobtest.java
index e08ff5b6fe1..654eaf92acd 100644
--- a/src/interfaces/jdbc/example/blobtest.java
+++ b/src/interfaces/jdbc/example/blobtest.java
@@ -24,224 +24,236 @@ import org.postgresql.largeobject.*;
public class blobtest
{
- Connection db;
- Statement s;
- LargeObjectManager lobj;
-
- public blobtest(String args[]) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException
- {
- String url = args[0];
- String usr = args[1];
- String pwd = args[2];
-
- // Load the driver
- Class.forName("org.postgresql.Driver");
-
- // Connect to database
- System.out.println("Connecting to Database URL = " + url);
- db = DriverManager.getConnection(url, usr, pwd);
-
- // This is required for all LargeObject calls
- System.out.println("Connected... First turn off autoCommit()");
- db.setAutoCommit(false);
-
- System.out.println("Now creating a statement");
- s = db.createStatement();
-
- // Now run tests using postgresql's own Large object api
- // NOTE: The methods shown in this example are _NOT_ JDBC, but are
- // an implementation of the calls found in libpq. Unless you need to
- // use this functionality, look at the jdbc tests on how to access blobs.
- ownapi();
-
- // Now run tests using JDBC methods
- //jdbcapi(db,s);
-
- // Finally close the database
- System.out.println("Now closing the connection");
- s.close();
- db.close();
-
- }
-
- /**
- * Now this is an extension to JDBC, unique to postgresql. Here we fetch
- * an PGlobj object, which provides us with access to postgresql's
- * large object api.
- */
- public void ownapi() throws FileNotFoundException, IOException, SQLException
- {
- System.out.println("\n----------------------------------------------------------------------\nTesting postgresql large object api\n----------------------------------------------------------------------\n");
-
- // Internally, the driver provides JDBC compliant methods to access large
- // objects, however the unique methods available to postgresql makes
- // things a little easier.
- System.out.println("Gaining access to large object api");
- lobj = ((org.postgresql.Connection)db).getLargeObjectAPI();
-
- int oid = ownapi_test1();
- ownapi_test2(oid);
-
- // Now call the jdbc2api test
- jdbc2api(oid);
-
- // finally delete the large object
- ownapi_test3(oid);
- System.out.println("\n\nOID="+oid);
- }
-
- private int ownapi_test1() throws FileNotFoundException, IOException, SQLException
- {
- System.out.println("Test 1 Creating a large object\n");
-
- // Ok, test 1 is to create a large object. To do this, we use the create
- // method.
- System.out.println("Creating a large object");
- int oid = lobj.create(LargeObjectManager.READ|LargeObjectManager.WRITE);
- DriverManager.println("got large object oid="+oid);
-
- LargeObject obj = lobj.open(oid,LargeObjectManager.WRITE);
- DriverManager.println("got large object obj="+obj);
-
- // Now open a test file - this class will do
- System.out.println("Opening test source object");
- FileInputStream fis = new FileInputStream("example/blobtest.java");
-
- // copy the data
- System.out.println("Copying file to large object");
- byte buf[] = new byte[2048];
- int s,tl=0;
- while((s=fis.read(buf,0,2048))>0) {
- System.out.println("Block size="+s+" offset="+tl);
- //System.out.write(buf);
- obj.write(buf,0,s);
- tl+=s;
- }
- DriverManager.println("Copied "+tl+" bytes");
-
- // Close the object
- System.out.println("Closing object");
- obj.close();
-
- return oid;
- }
-
- private void ownapi_test2(int oid) throws FileNotFoundException, IOException, SQLException
- {
- System.out.println("Test 2 Reading a large object and save as a file\n");
-
- // Now open the large object
- System.out.println("Opening large object "+oid);
- LargeObject obj = lobj.open(oid,LargeObjectManager.READ);
- DriverManager.println("got obj="+obj);
-
- // Now open a test file - this class will do
- System.out.println("Opening test destination object");
- FileOutputStream fos = new FileOutputStream("blob_testoutput");
-
- // copy the data
- System.out.println("Copying large object to file");
- byte buf[] = new byte[512];
- int s=obj.size();
- int tl=0;
- while(s>0) {
- int rs = buf.length;
- if(s<rs) rs=s;
- obj.read(buf,0,rs);
- fos.write(buf,0,rs);
- tl+=rs;
- s-=rs;
- }
- DriverManager.println("Copied "+tl+"/"+obj.size()+" bytes");
-
- // Close the object
- System.out.println("Closing object");
- obj.close();
- }
-
- private void ownapi_test3(int oid) throws SQLException
- {
- System.out.println("Test 3 Deleting a large object\n");
-
- // Now open the large object
- System.out.println("Deleting large object "+oid);
- lobj.unlink(oid);
- }
-
- //=======================================================================
- // This tests the Blob interface of the JDBC 2.0 specification
- public void jdbc2api(int oid) throws SQLException, IOException
- {
- System.out.println("Testing JDBC2 Blob interface:");
- jdbc2api_cleanup();
-
- System.out.println("Creating Blob on large object "+oid);
- s.executeUpdate("create table basic (a oid)");
-
- System.out.println("Inserting row");
- s.executeUpdate("insert into basic values ("+oid+")");
-
- System.out.println("Selecting row");
- ResultSet rs = s.executeQuery("select a from basic");
- if(rs!=null) {
- while(rs.next()) {
- System.out.println("Fetching Blob");
- Blob b = rs.getBlob("a");
- System.out.println("Blob.length() = "+b.length());
- System.out.println("Characters 400-500:");
- System.out.write(b.getBytes(400l,100));
- System.out.println();
- }
- rs.close();
+ Connection db;
+ Statement s;
+ LargeObjectManager lobj;
+
+ public blobtest(String args[]) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException
+ {
+ String url = args[0];
+ String usr = args[1];
+ String pwd = args[2];
+
+ // Load the driver
+ Class.forName("org.postgresql.Driver");
+
+ // Connect to database
+ System.out.println("Connecting to Database URL = " + url);
+ db = DriverManager.getConnection(url, usr, pwd);
+
+ // This is required for all LargeObject calls
+ System.out.println("Connected... First turn off autoCommit()");
+ db.setAutoCommit(false);
+
+ System.out.println("Now creating a statement");
+ s = db.createStatement();
+
+ // Now run tests using postgresql's own Large object api
+ // NOTE: The methods shown in this example are _NOT_ JDBC, but are
+ // an implementation of the calls found in libpq. Unless you need to
+ // use this functionality, look at the jdbc tests on how to access blobs.
+ ownapi();
+
+ // Now run tests using JDBC methods
+ //jdbcapi(db,s);
+
+ // Finally close the database
+ System.out.println("Now closing the connection");
+ s.close();
+ db.close();
+
+ }
+
+ /**
+ * Now this is an extension to JDBC, unique to postgresql. Here we fetch
+ * an PGlobj object, which provides us with access to postgresql's
+ * large object api.
+ */
+ public void ownapi() throws FileNotFoundException, IOException, SQLException
+ {
+ System.out.println("\n----------------------------------------------------------------------\nTesting postgresql large object api\n----------------------------------------------------------------------\n");
+
+ // Internally, the driver provides JDBC compliant methods to access large
+ // objects, however the unique methods available to postgresql makes
+ // things a little easier.
+ System.out.println("Gaining access to large object api");
+ lobj = ((org.postgresql.Connection)db).getLargeObjectAPI();
+
+ int oid = ownapi_test1();
+ ownapi_test2(oid);
+
+ // Now call the jdbc2api test
+ jdbc2api(oid);
+
+ // finally delete the large object
+ ownapi_test3(oid);
+ System.out.println("\n\nOID=" + oid);
+ }
+
+ private int ownapi_test1() throws FileNotFoundException, IOException, SQLException
+ {
+ System.out.println("Test 1 Creating a large object\n");
+
+ // Ok, test 1 is to create a large object. To do this, we use the create
+ // method.
+ System.out.println("Creating a large object");
+ int oid = lobj.create(LargeObjectManager.READ | LargeObjectManager.WRITE);
+ DriverManager.println("got large object oid=" + oid);
+
+ LargeObject obj = lobj.open(oid, LargeObjectManager.WRITE);
+ DriverManager.println("got large object obj=" + obj);
+
+ // Now open a test file - this class will do
+ System.out.println("Opening test source object");
+ FileInputStream fis = new FileInputStream("example/blobtest.java");
+
+ // copy the data
+ System.out.println("Copying file to large object");
+ byte buf[] = new byte[2048];
+ int s, tl = 0;
+ while ((s = fis.read(buf, 0, 2048)) > 0)
+ {
+ System.out.println("Block size=" + s + " offset=" + tl);
+ //System.out.write(buf);
+ obj.write(buf, 0, s);
+ tl += s;
+ }
+ DriverManager.println("Copied " + tl + " bytes");
+
+ // Close the object
+ System.out.println("Closing object");
+ obj.close();
+
+ return oid;
+ }
+
+ private void ownapi_test2(int oid) throws FileNotFoundException, IOException, SQLException
+ {
+ System.out.println("Test 2 Reading a large object and save as a file\n");
+
+ // Now open the large object
+ System.out.println("Opening large object " + oid);
+ LargeObject obj = lobj.open(oid, LargeObjectManager.READ);
+ DriverManager.println("got obj=" + obj);
+
+ // Now open a test file - this class will do
+ System.out.println("Opening test destination object");
+ FileOutputStream fos = new FileOutputStream("blob_testoutput");
+
+ // copy the data
+ System.out.println("Copying large object to file");
+ byte buf[] = new byte[512];
+ int s = obj.size();
+ int tl = 0;
+ while (s > 0)
+ {
+ int rs = buf.length;
+ if (s < rs)
+ rs = s;
+ obj.read(buf, 0, rs);
+ fos.write(buf, 0, rs);
+ tl += rs;
+ s -= rs;
+ }
+ DriverManager.println("Copied " + tl + "/" + obj.size() + " bytes");
+
+ // Close the object
+ System.out.println("Closing object");
+ obj.close();
+ }
+
+ private void ownapi_test3(int oid) throws SQLException
+ {
+ System.out.println("Test 3 Deleting a large object\n");
+
+ // Now open the large object
+ System.out.println("Deleting large object " + oid);
+ lobj.unlink(oid);
+ }
+
+ //=======================================================================
+ // This tests the Blob interface of the JDBC 2.0 specification
+ public void jdbc2api(int oid) throws SQLException, IOException
+ {
+ System.out.println("Testing JDBC2 Blob interface:");
+ jdbc2api_cleanup();
+
+ System.out.println("Creating Blob on large object " + oid);
+ s.executeUpdate("create table basic (a oid)");
+
+ System.out.println("Inserting row");
+ s.executeUpdate("insert into basic values (" + oid + ")");
+
+ System.out.println("Selecting row");
+ ResultSet rs = s.executeQuery("select a from basic");
+ if (rs != null)
+ {
+ while (rs.next())
+ {
+ System.out.println("Fetching Blob");
+ Blob b = rs.getBlob("a");
+ System.out.println("Blob.length() = " + b.length());
+ System.out.println("Characters 400-500:");
+ System.out.write(b.getBytes(400l, 100));
+ System.out.println();
+ }
+ rs.close();
+ }
+
+ System.out.println("Cleaning up");
+ jdbc2api_cleanup();
+ }
+
+ private void jdbc2api_cleanup() throws SQLException
+ {
+ db.setAutoCommit(true);
+ try
+ {
+ s.executeUpdate("drop table basic");
+ }
+ catch (Exception ex)
+ {
+ // We ignore any errors here
+ }
+ db.setAutoCommit(false);
+ }
+
+ //=======================================================================
+
+ public static void instructions()
+ {
+ System.err.println("java example.blobtest jdbc-url user password [debug]");
+ System.err.println("\nExamples:\n");
+ System.err.println("java -Djdbc.driver=org.postgresql.Driver example.blobtest jdbc:postgresql:test postgres password\nThis will run the tests on the database test on the local host.\n");
+ System.err.println("java -Djdbc.driver=org.postgresql.Driver example.blobtest jdbc:postgresql:test postgres password debug\nThis is the same as above, but will output debug information.\n");
+
+ System.err.println("This example tests the binary large object api of the driver.\nThis allows images or java objects to be stored in the database, and retrieved\nusing both postgresql's own api, and the standard JDBC api.");
}
-
- System.out.println("Cleaning up");
- jdbc2api_cleanup();
- }
-
- private void jdbc2api_cleanup() throws SQLException
- {
- db.setAutoCommit(true);
- try {
- s.executeUpdate("drop table basic");
- } catch(Exception ex) {
- // We ignore any errors here
+
+ public static void main(String args[])
+ {
+ System.out.println("PostgreSQL blobtest v7.0 rev 1\n");
+
+ if (args.length < 3)
+ {
+ instructions();
+ System.exit(1);
+ }
+
+ // This line outputs debug information to stderr. To enable this, simply
+ // add an extra parameter to the command line
+ if (args.length > 3)
+ DriverManager.setLogStream(System.err);
+
+ // Now run the tests
+ try
+ {
+ blobtest test = new blobtest(args);
+ }
+ catch (Exception ex)
+ {
+ System.err.println("Exception caught.\n" + ex);
+ ex.printStackTrace();
+ }
}
- db.setAutoCommit(false);
- }
-
- //=======================================================================
-
- public static void instructions()
- {
- System.err.println("java example.blobtest jdbc-url user password [debug]");
- System.err.println("\nExamples:\n");
- System.err.println("java -Djdbc.driver=org.postgresql.Driver example.blobtest jdbc:postgresql:test postgres password\nThis will run the tests on the database test on the local host.\n");
- System.err.println("java -Djdbc.driver=org.postgresql.Driver example.blobtest jdbc:postgresql:test postgres password debug\nThis is the same as above, but will output debug information.\n");
-
- System.err.println("This example tests the binary large object api of the driver.\nThis allows images or java objects to be stored in the database, and retrieved\nusing both postgresql's own api, and the standard JDBC api.");
- }
-
- public static void main(String args[])
- {
- System.out.println("PostgreSQL blobtest v7.0 rev 1\n");
-
- if(args.length<3) {
- instructions();
- System.exit(1);
- }
-
- // This line outputs debug information to stderr. To enable this, simply
- // add an extra parameter to the command line
- if(args.length>3)
- DriverManager.setLogStream(System.err);
-
- // Now run the tests
- try {
- blobtest test = new blobtest(args);
- } catch(Exception ex) {
- System.err.println("Exception caught.\n"+ex);
- ex.printStackTrace();
- }
- }
}
diff --git a/src/interfaces/jdbc/example/corba/StockClient.java b/src/interfaces/jdbc/example/corba/StockClient.java
index 7613f886fc1..0a357b15caf 100644
--- a/src/interfaces/jdbc/example/corba/StockClient.java
+++ b/src/interfaces/jdbc/example/corba/StockClient.java
@@ -9,280 +9,340 @@ import org.omg.CosNaming.*;
*
* 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 $
+ * $Id: StockClient.java,v 1.2 2001/10/25 05:59:58 momjian 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);
+ 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);
+
+ public static void main(String[] args)
+ {
+ new StockClient(args);
}
-
- mainMenu();
-
- // finally free the StockItem
- try {
- dispenser.releaseItem(item);
- } catch(Exception e) {
- System.out.println(e.toString());
- e.printStackTrace();
- System.exit(1);
+
+ 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)
+
+ private void mainMenu()
+ {
+ boolean run = true;
+ while (run)
{
- 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;
+ 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 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");
+
+ 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();
+ 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();
+
+ // 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();
+
+ // 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?")))
+
+ 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();
}
- }
- } 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;
- }
+
+ 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;
}
- 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);
+
+ 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;
}
- return false;
- }
}
diff --git a/src/interfaces/jdbc/example/corba/StockDB.java b/src/interfaces/jdbc/example/corba/StockDB.java
index f2ef2463c82..88797902ddb 100644
--- a/src/interfaces/jdbc/example/corba/StockDB.java
+++ b/src/interfaces/jdbc/example/corba/StockDB.java
@@ -13,105 +13,122 @@ import java.sql.*;
* 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.2 2000/04/26 05:32:01 peter Exp $
+ * $Id: StockDB.java,v 1.3 2001/10/25 05:59:58 momjian 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("org.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;
+ Connection con;
+ Statement st;
+
+ // the current stock number
+ int id = -1;
+
+ public void connect(String url, String usr, String pwd) throws Exception
+ {
+ Class.forName("org.postgresql.Driver");
+ System.out.println("Connecting to " + url);
+ con = DriverManager.getConnection(url, usr, pwd);
+ st = con.createStatement();
}
- 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;
+
+ public void closeConnection() throws Exception
+ {
+ con.close();
}
- 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;
+
+ public void fetchItem(int id) throws Exception
+ {
+ this.id = id;
}
- 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;
+
+ public int newItem() throws Exception
+ {
+ // tba
+ return -1;
}
- 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;
+
+ 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");
}
- 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
index 2d961a6dc7b..9572d20ae7f 100644
--- a/src/interfaces/jdbc/example/corba/StockDispenserImpl.java
+++ b/src/interfaces/jdbc/example/corba/StockDispenserImpl.java
@@ -5,79 +5,88 @@ 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 $
+ * $Id: StockDispenserImpl.java,v 1.2 2001/10/25 05:59:58 momjian 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();
+ 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;
- }
+
+ /**
+ * 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;
}
- 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;
- }
+
+ /**
+ * 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 ;
}
- 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;
+
+ /**
+ * This class defines a slot in the dispenser
+ */
+ class StockItemStatus
+ {
+ StockItemImpl ref;
+ boolean inUse;
+
+ StockItemStatus()
+ {
+ ref = null;
+ inUse = false;
+ }
}
- }
-
+
}
diff --git a/src/interfaces/jdbc/example/corba/StockItemImpl.java b/src/interfaces/jdbc/example/corba/StockItemImpl.java
index 7f6c5be9307..598ccd2ddcb 100644
--- a/src/interfaces/jdbc/example/corba/StockItemImpl.java
+++ b/src/interfaces/jdbc/example/corba/StockItemImpl.java
@@ -5,159 +5,204 @@ 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 $
+ * $Id: StockItemImpl.java,v 1.2 2001/10/25 05:59:58 momjian 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();
+ 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 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 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 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 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 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 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 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 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 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 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;
}
- }
-
- /**
- * This is used by our Dispenser
- */
- public String getInstanceName() {
- return instanceName;
- }
}
-
+
diff --git a/src/interfaces/jdbc/example/corba/StockServer.java b/src/interfaces/jdbc/example/corba/StockServer.java
index 6e34cbcd48d..43465a944e8 100644
--- a/src/interfaces/jdbc/example/corba/StockServer.java
+++ b/src/interfaces/jdbc/example/corba/StockServer.java
@@ -5,49 +5,54 @@ 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 $
+ * $Id: StockServer.java,v 1.2 2001/10/25 05:59:58 momjian 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();
+ 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();
+ }
}
- }
}
-
+
diff --git a/src/interfaces/jdbc/example/datestyle.java b/src/interfaces/jdbc/example/datestyle.java
index af8c87ae78e..53908c8c2fa 100644
--- a/src/interfaces/jdbc/example/datestyle.java
+++ b/src/interfaces/jdbc/example/datestyle.java
@@ -14,168 +14,176 @@ import java.text.*;
public class datestyle
{
- Connection db; // The connection to the database
- Statement st; // Our statement to run queries with
-
- // This is our standard to compare results with.
- java.sql.Date standard;
-
- // This is a list of the available date styles including variants.
- // These have to match what the "set datestyle" statement accepts.
- String styles[] = {
- "postgres,european",
- "postgres,us",
- "iso", // iso has no variants - us/european has no affect
- "sql,european",
- "sql,us",
- "german" // german has no variants - us/european has no affect
- };
-
- public datestyle(String args[]) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException
- {
- String url = args[0];
- String usr = args[1];
- String pwd = args[2];
-
- // Load the driver
- Class.forName("org.postgresql.Driver");
-
- // Connect to database
- System.out.println("Connecting to Database URL = " + url);
- db = DriverManager.getConnection(url, usr, pwd);
-
- System.out.println("Connected...Now creating a statement");
- st = db.createStatement();
-
- // Clean up the database (in case we failed earlier) then initialise
- cleanup();
- init();
-
- // Now run tests using JDBC methods
- doexample();
-
- // Clean up the database
- cleanup();
-
- // Finally close the database
- System.out.println("Now closing the connection");
- st.close();
- db.close();
-
- }
-
- /**
- * This drops the table (if it existed). No errors are reported.
- */
- public void cleanup()
- {
- try {
- st.executeUpdate("drop table datestyle");
- } catch(Exception ex) {
- // We ignore any errors here
- }
- }
-
- /**
- * This initialises the database for this example
- */
- public void init() throws SQLException
- {
- // Create a table holding a single date
- st.executeUpdate("create table datestyle (dt date)");
-
- // Now create our standard date for the test.
- //
- // NB: each component of the date should be different, otherwise the tests
- // will not be valid.
- //
- // NB: January = 0 here
- //
- standard = new java.sql.Date(98,0,8);
-
- // Now store the result.
- //
- // This is an example of how to set a date in a date style independent way.
- // The only way of doing this is by using a PreparedStatement.
- //
- PreparedStatement ps = db.prepareStatement("insert into datestyle values (?)");
- ps.setDate(1,standard);
- ps.executeUpdate();
- ps.close();
-
- }
-
- /**
- * This performs the example
- */
- public void doexample() throws SQLException
- {
- System.out.println("\nRunning tests:");
-
- for(int i=0;i<styles.length;i++) {
- System.out.print("Test "+i+" - "+styles[i]);
- System.out.flush();
-
- // set the style
- st.executeUpdate("set datestyle='"+styles[i]+"'");
-
- // Now because the driver needs to know what the current style is,
- // we have to run the following:
- st.executeUpdate("show datestyle");
- // This is a limitation, but there is no real way around this.
-
- // Now we query the table.
- ResultSet rs = st.executeQuery("select dt from datestyle");
-
- // Throw an exception if there is no result (if the table is empty
- // there should still be a result).
- if(rs==null)
- throw new SQLException("The test query returned no data");
-
- while(rs.next()) {
- // The JDBC spec states we should only read each column once.
- // In the current implementation of the driver, this is not necessary.
- // Here we use this fact to see what the query really returned.
- if(standard.equals(rs.getDate(1)))
- System.out.println(" passed, returned "+rs.getString(1));
- else
- System.out.println(" failed, returned "+rs.getString(1));
- }
- rs.close();
- }
- }
-
- /**
- * Display some instructions on how to run the example
- */
- public static void instructions()
- {
- System.out.println("\nThis example tests the drivers ability to handle dates correctly if the\nbackend is running any of the various date styles that it supports.\nIdealy this should work fine. If it doesn't, then there is something wrong\npossibly in postgresql.Connection or in the backend itself. If this does occur\nthen please email a bug report.\n");
- System.out.println("Useage:\n java example.datestyle jdbc:postgresql:database user password [debug]\n\nThe debug field can be anything. It's presence will enable DriverManager's\ndebug trace. Unless you want to see screens of items, don't put anything in\nhere.");
- System.exit(1);
- }
-
- /**
- * This little lot starts the test
- */
- public static void main(String args[])
- {
- System.out.println("PostgreSQL datestyle test v6.3 rev 1\n");
-
- if(args.length<3)
- instructions();
-
- // This line outputs debug information to stderr. To enable this, simply
- // add an extra parameter to the command line
- if(args.length>3)
- DriverManager.setLogStream(System.err);
-
- // Now run the tests
- try {
- datestyle test = new datestyle(args);
- } catch(Exception ex) {
- System.err.println("Exception caught.\n"+ex);
- ex.printStackTrace();
- }
- }
+ Connection db; // The connection to the database
+ Statement st; // Our statement to run queries with
+
+ // This is our standard to compare results with.
+ java.sql.Date standard;
+
+ // This is a list of the available date styles including variants.
+ // These have to match what the "set datestyle" statement accepts.
+ String styles[] = {
+ "postgres,european",
+ "postgres,us",
+ "iso", // iso has no variants - us/european has no affect
+ "sql,european",
+ "sql,us",
+ "german" // german has no variants - us/european has no affect
+ };
+
+ public datestyle(String args[]) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException
+ {
+ String url = args[0];
+ String usr = args[1];
+ String pwd = args[2];
+
+ // Load the driver
+ Class.forName("org.postgresql.Driver");
+
+ // Connect to database
+ System.out.println("Connecting to Database URL = " + url);
+ db = DriverManager.getConnection(url, usr, pwd);
+
+ System.out.println("Connected...Now creating a statement");
+ st = db.createStatement();
+
+ // Clean up the database (in case we failed earlier) then initialise
+ cleanup();
+ init();
+
+ // Now run tests using JDBC methods
+ doexample();
+
+ // Clean up the database
+ cleanup();
+
+ // Finally close the database
+ System.out.println("Now closing the connection");
+ st.close();
+ db.close();
+
+ }
+
+ /**
+ * This drops the table (if it existed). No errors are reported.
+ */
+ public void cleanup()
+ {
+ try
+ {
+ st.executeUpdate("drop table datestyle");
+ }
+ catch (Exception ex)
+ {
+ // We ignore any errors here
+ }
+ }
+
+ /**
+ * This initialises the database for this example
+ */
+ public void init() throws SQLException
+ {
+ // Create a table holding a single date
+ st.executeUpdate("create table datestyle (dt date)");
+
+ // Now create our standard date for the test.
+ //
+ // NB: each component of the date should be different, otherwise the tests
+ // will not be valid.
+ //
+ // NB: January = 0 here
+ //
+ standard = new java.sql.Date(98, 0, 8);
+
+ // Now store the result.
+ //
+ // This is an example of how to set a date in a date style independent way.
+ // The only way of doing this is by using a PreparedStatement.
+ //
+ PreparedStatement ps = db.prepareStatement("insert into datestyle values (?)");
+ ps.setDate(1, standard);
+ ps.executeUpdate();
+ ps.close();
+
+ }
+
+ /**
+ * This performs the example
+ */
+ public void doexample() throws SQLException
+ {
+ System.out.println("\nRunning tests:");
+
+ for (int i = 0;i < styles.length;i++)
+ {
+ System.out.print("Test " + i + " - " + styles[i]);
+ System.out.flush();
+
+ // set the style
+ st.executeUpdate("set datestyle='" + styles[i] + "'");
+
+ // Now because the driver needs to know what the current style is,
+ // we have to run the following:
+ st.executeUpdate("show datestyle");
+ // This is a limitation, but there is no real way around this.
+
+ // Now we query the table.
+ ResultSet rs = st.executeQuery("select dt from datestyle");
+
+ // Throw an exception if there is no result (if the table is empty
+ // there should still be a result).
+ if (rs == null)
+ throw new SQLException("The test query returned no data");
+
+ while (rs.next())
+ {
+ // The JDBC spec states we should only read each column once.
+ // In the current implementation of the driver, this is not necessary.
+ // Here we use this fact to see what the query really returned.
+ if (standard.equals(rs.getDate(1)))
+ System.out.println(" passed, returned " + rs.getString(1));
+ else
+ System.out.println(" failed, returned " + rs.getString(1));
+ }
+ rs.close();
+ }
+ }
+
+ /**
+ * Display some instructions on how to run the example
+ */
+ public static void instructions()
+ {
+ System.out.println("\nThis example tests the drivers ability to handle dates correctly if the\nbackend is running any of the various date styles that it supports.\nIdealy this should work fine. If it doesn't, then there is something wrong\npossibly in postgresql.Connection or in the backend itself. If this does occur\nthen please email a bug report.\n");
+ System.out.println("Useage:\n java example.datestyle jdbc:postgresql:database user password [debug]\n\nThe debug field can be anything. It's presence will enable DriverManager's\ndebug trace. Unless you want to see screens of items, don't put anything in\nhere.");
+ System.exit(1);
+ }
+
+ /**
+ * This little lot starts the test
+ */
+ public static void main(String args[])
+ {
+ System.out.println("PostgreSQL datestyle test v6.3 rev 1\n");
+
+ if (args.length < 3)
+ instructions();
+
+ // This line outputs debug information to stderr. To enable this, simply
+ // add an extra parameter to the command line
+ if (args.length > 3)
+ DriverManager.setLogStream(System.err);
+
+ // Now run the tests
+ try
+ {
+ datestyle test = new datestyle(args);
+ }
+ catch (Exception ex)
+ {
+ System.err.println("Exception caught.\n" + ex);
+ ex.printStackTrace();
+ }
+ }
}
diff --git a/src/interfaces/jdbc/example/metadata.java b/src/interfaces/jdbc/example/metadata.java
index 8d674122739..182e4533e0c 100644
--- a/src/interfaces/jdbc/example/metadata.java
+++ b/src/interfaces/jdbc/example/metadata.java
@@ -15,260 +15,284 @@ import java.text.*;
public class metadata
{
- Connection db; // The connection to the database
- Statement st; // Our statement to run queries with
- DatabaseMetaData dbmd; // This defines the structure of the database
-
- /**
- * These are the available tests on DatabaseMetaData
- */
- public void doDatabaseMetaData() throws SQLException {
- if(doTest("getProcedures() - should show all available procedures"))
- displayResult(dbmd.getProcedures(null,null,null));
-
- if(doTest("getProcedures() with pattern - should show all circle procedures"))
- displayResult(dbmd.getProcedures(null,null,"circle%"));
-
- if(doTest("getProcedureColumns() on circle procedures"))
- displayResult(dbmd.getProcedureColumns(null,null,"circle%",null));
-
- if(doTest("getTables()"))
- displayResult(dbmd.getTables(null,null,null,null));
-
- if(doTest("getColumns() - should show all tables, can take a while to run"))
- displayResult(dbmd.getColumns(null,null,null,null));
-
- if(doTest("getColumns() - should show the test_b table"))
- displayResult(dbmd.getColumns(null,null,"test_b",null));
-
- if(doTest("getColumnPrivileges() - should show all tables"))
- displayResult(dbmd.getColumnPrivileges(null,null,null,null));
-
- if(doTest("getPrimaryKeys()"))
- displayResult(dbmd.getPrimaryKeys(null,null,null));
-
- if(doTest("getTypeInfo()"))
- displayResult(dbmd.getTypeInfo());
-
- }
-
- /**
- * These are the available tests on ResultSetMetaData
- */
- public void doResultSetMetaData() throws SQLException {
-
- String sql = "select imagename,descr,source,cost from test_a,test_b,test_c where test_a.id=test_b.imageid and test_a.id=test_c.imageid";
-
- System.out.println("Executing query for tests");
- ResultSet rs = st.executeQuery(sql);
- ResultSetMetaData rsmd = rs.getMetaData();
-
- if(doTest("isCurrency()"))
- System.out.println("isCurrency on col 1 = "+rsmd.isCurrency(1)+" should be false\nisCurrency on col 4 = "+rsmd.isCurrency(4)+" should be true");
-
- // Finally close the query. Now give the user a chance to display the
- // ResultSet.
- //
- // NB: displayResult() actually closes the ResultSet.
- if(doTest("Display query result")) {
- System.out.println("Query: "+sql);
- displayResult(rs);
- } else
- rs.close();
- }
-
- /**
- * This creates some test data
- */
- public void init() throws SQLException {
- System.out.println("Creating some tables");
- cleanup();
- st.executeUpdate("create table test_a (imagename name,image oid,id int4)");
- st.executeUpdate("create table test_b (descr text,imageid int4,id int4)");
- st.executeUpdate("create table test_c (source text,cost money,imageid int4)");
-
- System.out.println("Adding some data");
- st.executeUpdate("insert into test_a values ('test1',0,1)");
- st.executeUpdate("insert into test_b values ('A test description',1,2)");
- st.executeUpdate("insert into test_c values ('nowhere particular','$10.99',1)");
- }
-
- /**
- * This removes the test data
- */
- public void cleanup() throws SQLException {
- try {
- st.executeUpdate("drop table test_a");
- st.executeUpdate("drop table test_b");
- st.executeUpdate("drop table test_c");
- } catch(Exception ex) {
- // We ignore any errors here
- }
- }
-
- public metadata(String args[]) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException
- {
- String url = args[0];
- String usr = args[1];
- String pwd = args[2];
-
- // Load the driver
- Class.forName("org.postgresql.Driver");
-
- // Connect to database
- System.out.println("Connecting to Database URL = " + url);
- db = DriverManager.getConnection(url, usr, pwd);
-
- dbmd = db.getMetaData();
- st = db.createStatement();
-
- // This prints the backend's version
- System.out.println("Connected to "+dbmd.getDatabaseProductName()+" "+dbmd.getDatabaseProductVersion());
-
- init();
-
- System.out.println();
-
- // Now the tests
- if(doTest("Test DatabaseMetaData"))
- doDatabaseMetaData();
-
- if(doTest("Test ResultSetMetaData"))
- doResultSetMetaData();
-
- System.out.println("\nNow closing the connection");
- st.close();
- db.close();
-
- cleanup();
- }
-
- /**
- * This asks if the user requires to run a test.
- */
- public boolean doTest(String s) {
- System.out.println();
- System.out.print(s);
- System.out.print(" Perform test? Y or N:");
- System.out.flush();
- char c = ' ';
- try {
- while(!(c=='n' || c=='y' || c=='N' || c=='Y')) {
- c=(char)System.in.read();
- }
- } catch(IOException ioe) {
- return false;
- }
-
- return c=='y' || c=='Y';
- }
-
- /**
- * This displays a result set.
- * Note: it closes the result once complete.
- */
- public void displayResult(ResultSet rs) throws SQLException
- {
- ResultSetMetaData rsmd = rs.getMetaData();
- int count=0;
-
- // Print the result column names
- int cols = rsmd.getColumnCount();
- for(int i=1;i<=cols;i++)
- System.out.print(rsmd.getColumnLabel(i)+(i<cols?"\t":"\n"));
-
- // now the results
- while(rs.next()) {
- count++;
- for(int i=1;i<=cols;i++) {
- Object o = rs.getObject(i);
- if(rs.wasNull())
- System.out.print("{null}"+(i<cols?"\t":"\n"));
- else
- System.out.print(o.toString()+(i<cols?"\t":"\n"));
- }
- }
-
- System.out.println("Result returned "+count+" rows.");
-
- // finally close the result set
- rs.close();
- }
-
- /**
- * This process / commands (for now just /d)
- */
- public void processSlashCommand(String line) throws SQLException
- {
- if(line.startsWith("\\d")) {
-
- if(line.startsWith("\\d ")) {
- // Display details about a table
- String table=line.substring(3);
- displayResult(dbmd.getColumns(null,null,table,"%"));
- } else {
- String types[] = null;
- if(line.equals("\\d"))
- types=allUserTables;
- else if(line.equals("\\di"))
- types=usrIndices;
- else if(line.equals("\\dt"))
- types=usrTables;
- else if(line.equals("\\ds"))
- types=usrSequences;
- else if(line.equals("\\dS"))
- types=sysTables;
- else
- throw new SQLException("Unsupported \\d command: "+line);
-
- // Display details about all system tables
- //
- // Note: the first two arguments are ignored. To keep to the spec,
- // you must put null here
- //
- displayResult(dbmd.getTables(null,null,"%",types));
- }
- } else
- throw new SQLException("Unsupported \\ command: "+line);
- }
-
- private static final String allUserTables[] = {"TABLE","INDEX","SEQUENCE"};
- private static final String usrIndices[] = {"INDEX"};
- private static final String usrTables[] = {"TABLE"};
- private static final String usrSequences[] = {"SEQUENCE"};
- private static final String sysTables[] = {"SYSTEM TABLE","SYSTEM INDEX"};
-
- /**
- * Display some instructions on how to run the example
- */
- public static void instructions()
- {
- System.out.println("\nThis is not really an example, but is used to test the various methods in\nthe DatabaseMetaData and ResultSetMetaData classes.\n");
- System.out.println("Useage:\n java example.metadata jdbc:postgresql:database user password [debug]\n\nThe debug field can be anything. It's presence will enable DriverManager's\ndebug trace. Unless you want to see screens of debug items, don't put anything in\nhere.");
- System.exit(1);
- }
-
- /**
- * This little lot starts the test
- */
- public static void main(String args[])
- {
- System.out.println("PostgreSQL metdata tester v6.4 rev 1\n");
-
- if(args.length<3)
- instructions();
-
- // This line outputs debug information to stderr. To enable this, simply
- // add an extra parameter to the command line
- if(args.length>3)
- DriverManager.setLogStream(System.err);
-
- // Now run the tests
- try {
- metadata test = new metadata(args);
- } catch(Exception ex) {
- System.err.println("Exception caught.\n"+ex);
- ex.printStackTrace();
- }
- }
+ Connection db; // The connection to the database
+ Statement st; // Our statement to run queries with
+ DatabaseMetaData dbmd; // This defines the structure of the database
+
+ /**
+ * These are the available tests on DatabaseMetaData
+ */
+ public void doDatabaseMetaData() throws SQLException
+ {
+ if (doTest("getProcedures() - should show all available procedures"))
+ displayResult(dbmd.getProcedures(null, null, null));
+
+ if (doTest("getProcedures() with pattern - should show all circle procedures"))
+ displayResult(dbmd.getProcedures(null, null, "circle%"));
+
+ if (doTest("getProcedureColumns() on circle procedures"))
+ displayResult(dbmd.getProcedureColumns(null, null, "circle%", null));
+
+ if (doTest("getTables()"))
+ displayResult(dbmd.getTables(null, null, null, null));
+
+ if (doTest("getColumns() - should show all tables, can take a while to run"))
+ displayResult(dbmd.getColumns(null, null, null, null));
+
+ if (doTest("getColumns() - should show the test_b table"))
+ displayResult(dbmd.getColumns(null, null, "test_b", null));
+
+ if (doTest("getColumnPrivileges() - should show all tables"))
+ displayResult(dbmd.getColumnPrivileges(null, null, null, null));
+
+ if (doTest("getPrimaryKeys()"))
+ displayResult(dbmd.getPrimaryKeys(null, null, null));
+
+ if (doTest("getTypeInfo()"))
+ displayResult(dbmd.getTypeInfo());
+
+ }
+
+ /**
+ * These are the available tests on ResultSetMetaData
+ */
+ public void doResultSetMetaData() throws SQLException
+ {
+
+ String sql = "select imagename,descr,source,cost from test_a,test_b,test_c where test_a.id=test_b.imageid and test_a.id=test_c.imageid";
+
+ System.out.println("Executing query for tests");
+ ResultSet rs = st.executeQuery(sql);
+ ResultSetMetaData rsmd = rs.getMetaData();
+
+ if (doTest("isCurrency()"))
+ System.out.println("isCurrency on col 1 = " + rsmd.isCurrency(1) + " should be false\nisCurrency on col 4 = " + rsmd.isCurrency(4) + " should be true");
+
+ // Finally close the query. Now give the user a chance to display the
+ // ResultSet.
+ //
+ // NB: displayResult() actually closes the ResultSet.
+ if (doTest("Display query result"))
+ {
+ System.out.println("Query: " + sql);
+ displayResult(rs);
+ }
+ else
+ rs.close();
+ }
+
+ /**
+ * This creates some test data
+ */
+ public void init() throws SQLException
+ {
+ System.out.println("Creating some tables");
+ cleanup();
+ st.executeUpdate("create table test_a (imagename name,image oid,id int4)");
+ st.executeUpdate("create table test_b (descr text,imageid int4,id int4)");
+ st.executeUpdate("create table test_c (source text,cost money,imageid int4)");
+
+ System.out.println("Adding some data");
+ st.executeUpdate("insert into test_a values ('test1',0,1)");
+ st.executeUpdate("insert into test_b values ('A test description',1,2)");
+ st.executeUpdate("insert into test_c values ('nowhere particular','$10.99',1)");
+ }
+
+ /**
+ * This removes the test data
+ */
+ public void cleanup() throws SQLException
+ {
+ try
+ {
+ st.executeUpdate("drop table test_a");
+ st.executeUpdate("drop table test_b");
+ st.executeUpdate("drop table test_c");
+ }
+ catch (Exception ex)
+ {
+ // We ignore any errors here
+ }
+ }
+
+ public metadata(String args[]) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException
+ {
+ String url = args[0];
+ String usr = args[1];
+ String pwd = args[2];
+
+ // Load the driver
+ Class.forName("org.postgresql.Driver");
+
+ // Connect to database
+ System.out.println("Connecting to Database URL = " + url);
+ db = DriverManager.getConnection(url, usr, pwd);
+
+ dbmd = db.getMetaData();
+ st = db.createStatement();
+
+ // This prints the backend's version
+ System.out.println("Connected to " + dbmd.getDatabaseProductName() + " " + dbmd.getDatabaseProductVersion());
+
+ init();
+
+ System.out.println();
+
+ // Now the tests
+ if (doTest("Test DatabaseMetaData"))
+ doDatabaseMetaData();
+
+ if (doTest("Test ResultSetMetaData"))
+ doResultSetMetaData();
+
+ System.out.println("\nNow closing the connection");
+ st.close();
+ db.close();
+
+ cleanup();
+ }
+
+ /**
+ * This asks if the user requires to run a test.
+ */
+ public boolean doTest(String s)
+ {
+ System.out.println();
+ System.out.print(s);
+ System.out.print(" Perform test? Y or N:");
+ System.out.flush();
+ char c = ' ';
+ try
+ {
+ while (!(c == 'n' || c == 'y' || c == 'N' || c == 'Y'))
+ {
+ c = (char)System.in.read();
+ }
+ }
+ catch (IOException ioe)
+ {
+ return false;
+ }
+
+ return c == 'y' || c == 'Y';
+ }
+
+ /**
+ * This displays a result set.
+ * Note: it closes the result once complete.
+ */
+ public void displayResult(ResultSet rs) throws SQLException
+ {
+ ResultSetMetaData rsmd = rs.getMetaData();
+ int count = 0;
+
+ // Print the result column names
+ int cols = rsmd.getColumnCount();
+ for (int i = 1;i <= cols;i++)
+ System.out.print(rsmd.getColumnLabel(i) + (i < cols ? "\t" : "\n"));
+
+ // now the results
+ while (rs.next())
+ {
+ count++;
+ for (int i = 1;i <= cols;i++)
+ {
+ Object o = rs.getObject(i);
+ if (rs.wasNull())
+ System.out.print("{null}" + (i < cols ? "\t" : "\n"));
+ else
+ System.out.print(o.toString() + (i < cols ? "\t" : "\n"));
+ }
+ }
+
+ System.out.println("Result returned " + count + " rows.");
+
+ // finally close the result set
+ rs.close();
+ }
+
+ /**
+ * This process / commands (for now just /d)
+ */
+ public void processSlashCommand(String line) throws SQLException
+ {
+ if (line.startsWith("\\d"))
+ {
+
+ if (line.startsWith("\\d "))
+ {
+ // Display details about a table
+ String table = line.substring(3);
+ displayResult(dbmd.getColumns(null, null, table, "%"));
+ }
+ else
+ {
+ String types[] = null;
+ if (line.equals("\\d"))
+ types = allUserTables;
+ else if (line.equals("\\di"))
+ types = usrIndices;
+ else if (line.equals("\\dt"))
+ types = usrTables;
+ else if (line.equals("\\ds"))
+ types = usrSequences;
+ else if (line.equals("\\dS"))
+ types = sysTables;
+ else
+ throw new SQLException("Unsupported \\d command: " + line);
+
+ // Display details about all system tables
+ //
+ // Note: the first two arguments are ignored. To keep to the spec,
+ // you must put null here
+ //
+ displayResult(dbmd.getTables(null, null, "%", types));
+ }
+ }
+ else
+ throw new SQLException("Unsupported \\ command: " + line);
+ }
+
+ private static final String allUserTables[] = {"TABLE", "INDEX", "SEQUENCE"};
+ private static final String usrIndices[] = {"INDEX"};
+ private static final String usrTables[] = {"TABLE"};
+ private static final String usrSequences[] = {"SEQUENCE"};
+ private static final String sysTables[] = {"SYSTEM TABLE", "SYSTEM INDEX"};
+
+ /**
+ * Display some instructions on how to run the example
+ */
+ public static void instructions()
+ {
+ System.out.println("\nThis is not really an example, but is used to test the various methods in\nthe DatabaseMetaData and ResultSetMetaData classes.\n");
+ System.out.println("Useage:\n java example.metadata jdbc:postgresql:database user password [debug]\n\nThe debug field can be anything. It's presence will enable DriverManager's\ndebug trace. Unless you want to see screens of debug items, don't put anything in\nhere.");
+ System.exit(1);
+ }
+
+ /**
+ * This little lot starts the test
+ */
+ public static void main(String args[])
+ {
+ System.out.println("PostgreSQL metdata tester v6.4 rev 1\n");
+
+ if (args.length < 3)
+ instructions();
+
+ // This line outputs debug information to stderr. To enable this, simply
+ // add an extra parameter to the command line
+ if (args.length > 3)
+ DriverManager.setLogStream(System.err);
+
+ // Now run the tests
+ try
+ {
+ metadata test = new metadata(args);
+ }
+ catch (Exception ex)
+ {
+ System.err.println("Exception caught.\n" + ex);
+ ex.printStackTrace();
+ }
+ }
}
diff --git a/src/interfaces/jdbc/example/psql.java b/src/interfaces/jdbc/example/psql.java
index 9e63ad8129e..b3fd308cd7b 100644
--- a/src/interfaces/jdbc/example/psql.java
+++ b/src/interfaces/jdbc/example/psql.java
@@ -1,213 +1,236 @@
-package example;
-
-import java.io.*;
-import java.sql.*;
-import java.text.*;
-
-/**
- * This example application demonstrates some of the drivers other features
- * by implementing a simple psql replacement in Java.
- *
- */
-
-public class psql
-{
- Connection db; // The connection to the database
- Statement st; // Our statement to run queries with
- DatabaseMetaData dbmd; // This defines the structure of the database
- boolean done = false; // Added by CWJ to permit \q command
-
- public psql(String args[]) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException
- {
- String url = args[0];
- String usr = args[1];
- String pwd = args[2];
-
- // Load the driver
- Class.forName("org.postgresql.Driver");
-
- // Connect to database
- System.out.println("Connecting to Database URL = " + url);
- db = DriverManager.getConnection(url, usr, pwd);
-
- dbmd = db.getMetaData();
- st = db.createStatement();
-
- // This prints the backend's version
- System.out.println("Connected to "+dbmd.getDatabaseProductName()+" "+dbmd.getDatabaseProductVersion());
-
- System.out.println();
-
- // This provides us the means of reading from stdin
- StreamTokenizer input = new StreamTokenizer(new InputStreamReader(System.in));
- input.resetSyntax();
- input.slashSlashComments(true); // allow // as a comment delimiter
- input.eolIsSignificant(false); // treat eol's as spaces
- input.wordChars(32,126);
- input.whitespaceChars(59,59);
- // input.quoteChar(39); *** CWJ: messes up literals in query string ***
-
- // Now the main loop.
- int tt=0,lineno=1;
- while(tt!=StreamTokenizer.TT_EOF && ! done) { // done added by CWJ to permit \q command
- System.out.print("["+lineno+"] ");
- System.out.flush();
-
- // Here, we trap SQLException so they don't terminate the application
- try {
- if((tt=input.nextToken())==StreamTokenizer.TT_WORD) {
- processLine(input.sval);
- lineno++;
- }
- } catch(SQLException ex) {
- System.out.println(ex.getMessage());
- }
- }
-
- System.out.println("Now closing the connection");
- st.close();
- db.close();
-
- }
-
- /**
- * This processes a statement
- */
- public void processLine(String line) throws SQLException
- {
- if(line.startsWith("\\")) {
- processSlashCommand(line);
- return;
- }
-
- boolean type = st.execute(line);
- boolean loop=true;
- while(loop) {
- if(type) {
- // A ResultSet was returned
- ResultSet rs=st.getResultSet();
- displayResult(rs);
- } else {
- int count = st.getUpdateCount();
-
- if(count==-1) {
- // This indicates nothing left
- loop=false;
- } else {
- // An update count was returned
- System.out.println("Updated "+st.getUpdateCount()+" rows");
- }
- }
-
- if(loop)
- type = st.getMoreResults();
- }
- }
-
- /**
- * This displays a result set.
- * Note: it closes the result once complete.
- */
- public void displayResult(ResultSet rs) throws SQLException
- {
- ResultSetMetaData rsmd = rs.getMetaData();
-
- // Print the result column names
- int cols = rsmd.getColumnCount();
- for(int i=1;i<=cols;i++)
- System.out.print(rsmd.getColumnLabel(i)+(i<cols?"\t":"\n"));
-
- // now the results
- while(rs.next()) {
- for(int i=1;i<=cols;i++) {
- Object o = rs.getObject(i);
- if(rs.wasNull())
- System.out.print("{null}"+(i<cols?"\t":"\n"));
- else
- System.out.print(o.toString()+(i<cols?"\t":"\n"));
- }
- }
-
- // finally close the result set
- rs.close();
- }
-
- /**
- * This process / commands (for now just /d)
- */
- public void processSlashCommand(String line) throws SQLException
- {
- if(line.startsWith("\\d")) {
-
- if(line.startsWith("\\d ")) {
- // Display details about a table
- String table=line.substring(3);
- displayResult(dbmd.getColumns(null,null,table,"%"));
- } else {
- String types[] = null;
- if(line.equals("\\d"))
- types=allUserTables;
- else if(line.equals("\\di"))
- types=usrIndices;
- else if(line.equals("\\dt"))
- types=usrTables;
- else if(line.equals("\\ds"))
- types=usrSequences;
- else if(line.equals("\\dS"))
- types=sysTables;
- else
- throw new SQLException("Unsupported \\d command: "+line);
-
- // Display details about all system tables
- //
- // Note: the first two arguments are ignored. To keep to the spec,
- // you must put null here
- //
- displayResult(dbmd.getTables(null,null,"%",types));
- }
- } else if(line.equals("\\q")) // Added by CWJ to permit \q command
- done = true;
- else
- throw new SQLException("Unsupported \\ command: "+line);
- }
-
- private static final String allUserTables[] = {"TABLE","INDEX","SEQUENCE"};
- private static final String usrIndices[] = {"INDEX"};
- private static final String usrTables[] = {"TABLE"};
- private static final String usrSequences[] = {"SEQUENCE"};
- private static final String sysTables[] = {"SYSTEM TABLE","SYSTEM INDEX"};
-
- /**
- * Display some instructions on how to run the example
- */
- public static void instructions()
- {
- System.out.println("\nThis example shows how some of the other JDBC features work within the\ndriver. It does this by implementing a very simple psql equivalent in java.\nNot everything that psql does is implemented.\n");
- System.out.println("Useage:\n java example.psql jdbc:postgresql:database user password [debug]\n\nThe debug field can be anything. It's presence will enable DriverManager's\ndebug trace. Unless you want to see screens of items, don't put anything in\nhere.");
- System.exit(1);
- }
-
- /**
- * This little lot starts the test
- */
- public static void main(String args[])
- {
- System.out.println("PostgreSQL psql example v6.3 rev 1\n");
-
- if(args.length<3)
- instructions();
-
- // This line outputs debug information to stderr. To enable this, simply
- // add an extra parameter to the command line
- if(args.length>3)
- DriverManager.setLogStream(System.err);
-
- // Now run the tests
- try {
- psql test = new psql(args);
- } catch(Exception ex) {
- System.err.println("Exception caught.\n"+ex);
- ex.printStackTrace();
- }
- }
-}
+package example;
+
+import java.io.*;
+import java.sql.*;
+import java.text.*;
+
+/**
+ * This example application demonstrates some of the drivers other features
+ * by implementing a simple psql replacement in Java.
+ *
+ */
+
+public class psql
+{
+ Connection db; // The connection to the database
+ Statement st; // Our statement to run queries with
+ DatabaseMetaData dbmd; // This defines the structure of the database
+ boolean done = false; // Added by CWJ to permit \q command
+
+ public psql(String args[]) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException
+ {
+ String url = args[0];
+ String usr = args[1];
+ String pwd = args[2];
+
+ // Load the driver
+ Class.forName("org.postgresql.Driver");
+
+ // Connect to database
+ System.out.println("Connecting to Database URL = " + url);
+ db = DriverManager.getConnection(url, usr, pwd);
+
+ dbmd = db.getMetaData();
+ st = db.createStatement();
+
+ // This prints the backend's version
+ System.out.println("Connected to " + dbmd.getDatabaseProductName() + " " + dbmd.getDatabaseProductVersion());
+
+ System.out.println();
+
+ // This provides us the means of reading from stdin
+ StreamTokenizer input = new StreamTokenizer(new InputStreamReader(System.in));
+ input.resetSyntax();
+ input.slashSlashComments(true); // allow // as a comment delimiter
+ input.eolIsSignificant(false); // treat eol's as spaces
+ input.wordChars(32, 126);
+ input.whitespaceChars(59, 59);
+ // input.quoteChar(39); *** CWJ: messes up literals in query string ***
+
+ // Now the main loop.
+ int tt = 0, lineno = 1;
+ while (tt != StreamTokenizer.TT_EOF && ! done)
+ { // done added by CWJ to permit \q command
+ System.out.print("[" + lineno + "] ");
+ System.out.flush();
+
+ // Here, we trap SQLException so they don't terminate the application
+ try
+ {
+ if ((tt = input.nextToken()) == StreamTokenizer.TT_WORD)
+ {
+ processLine(input.sval);
+ lineno++;
+ }
+ }
+ catch (SQLException ex)
+ {
+ System.out.println(ex.getMessage());
+ }
+ }
+
+ System.out.println("Now closing the connection");
+ st.close();
+ db.close();
+
+ }
+
+ /**
+ * This processes a statement
+ */
+ public void processLine(String line) throws SQLException
+ {
+ if (line.startsWith("\\"))
+ {
+ processSlashCommand(line);
+ return ;
+ }
+
+ boolean type = st.execute(line);
+ boolean loop = true;
+ while (loop)
+ {
+ if (type)
+ {
+ // A ResultSet was returned
+ ResultSet rs = st.getResultSet();
+ displayResult(rs);
+ }
+ else
+ {
+ int count = st.getUpdateCount();
+
+ if (count == -1)
+ {
+ // This indicates nothing left
+ loop = false;
+ }
+ else
+ {
+ // An update count was returned
+ System.out.println("Updated " + st.getUpdateCount() + " rows");
+ }
+ }
+
+ if (loop)
+ type = st.getMoreResults();
+ }
+ }
+
+ /**
+ * This displays a result set.
+ * Note: it closes the result once complete.
+ */
+ public void displayResult(ResultSet rs) throws SQLException
+ {
+ ResultSetMetaData rsmd = rs.getMetaData();
+
+ // Print the result column names
+ int cols = rsmd.getColumnCount();
+ for (int i = 1;i <= cols;i++)
+ System.out.print(rsmd.getColumnLabel(i) + (i < cols ? "\t" : "\n"));
+
+ // now the results
+ while (rs.next())
+ {
+ for (int i = 1;i <= cols;i++)
+ {
+ Object o = rs.getObject(i);
+ if (rs.wasNull())
+ System.out.print("{null}" + (i < cols ? "\t" : "\n"));
+ else
+ System.out.print(o.toString() + (i < cols ? "\t" : "\n"));
+ }
+ }
+
+ // finally close the result set
+ rs.close();
+ }
+
+ /**
+ * This process / commands (for now just /d)
+ */
+ public void processSlashCommand(String line) throws SQLException
+ {
+ if (line.startsWith("\\d"))
+ {
+
+ if (line.startsWith("\\d "))
+ {
+ // Display details about a table
+ String table = line.substring(3);
+ displayResult(dbmd.getColumns(null, null, table, "%"));
+ }
+ else
+ {
+ String types[] = null;
+ if (line.equals("\\d"))
+ types = allUserTables;
+ else if (line.equals("\\di"))
+ types = usrIndices;
+ else if (line.equals("\\dt"))
+ types = usrTables;
+ else if (line.equals("\\ds"))
+ types = usrSequences;
+ else if (line.equals("\\dS"))
+ types = sysTables;
+ else
+ throw new SQLException("Unsupported \\d command: " + line);
+
+ // Display details about all system tables
+ //
+ // Note: the first two arguments are ignored. To keep to the spec,
+ // you must put null here
+ //
+ displayResult(dbmd.getTables(null, null, "%", types));
+ }
+ }
+ else if (line.equals("\\q")) // Added by CWJ to permit \q command
+ done = true;
+ else
+ throw new SQLException("Unsupported \\ command: " + line);
+ }
+
+ private static final String allUserTables[] = {"TABLE", "INDEX", "SEQUENCE"};
+ private static final String usrIndices[] = {"INDEX"};
+ private static final String usrTables[] = {"TABLE"};
+ private static final String usrSequences[] = {"SEQUENCE"};
+ private static final String sysTables[] = {"SYSTEM TABLE", "SYSTEM INDEX"};
+
+ /**
+ * Display some instructions on how to run the example
+ */
+ public static void instructions()
+ {
+ System.out.println("\nThis example shows how some of the other JDBC features work within the\ndriver. It does this by implementing a very simple psql equivalent in java.\nNot everything that psql does is implemented.\n");
+ System.out.println("Useage:\n java example.psql jdbc:postgresql:database user password [debug]\n\nThe debug field can be anything. It's presence will enable DriverManager's\ndebug trace. Unless you want to see screens of items, don't put anything in\nhere.");
+ System.exit(1);
+ }
+
+ /**
+ * This little lot starts the test
+ */
+ public static void main(String args[])
+ {
+ System.out.println("PostgreSQL psql example v6.3 rev 1\n");
+
+ if (args.length < 3)
+ instructions();
+
+ // This line outputs debug information to stderr. To enable this, simply
+ // add an extra parameter to the command line
+ if (args.length > 3)
+ DriverManager.setLogStream(System.err);
+
+ // Now run the tests
+ try
+ {
+ psql test = new psql(args);
+ }
+ catch (Exception ex)
+ {
+ System.err.println("Exception caught.\n" + ex);
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/src/interfaces/jdbc/example/threadsafe.java b/src/interfaces/jdbc/example/threadsafe.java
index ea69143d8d0..2931221f181 100644
--- a/src/interfaces/jdbc/example/threadsafe.java
+++ b/src/interfaces/jdbc/example/threadsafe.java
@@ -18,350 +18,388 @@ import org.postgresql.largeobject.*;
public class threadsafe
{
- Connection db; // The connection to the database
- Statement st; // Our statement to run queries with
-
- public threadsafe(String args[]) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException
- {
- String url = args[0];
- String usr = args[1];
- String pwd = args[2];
-
- // Load the driver
- Class.forName("org.postgresql.Driver");
-
- // Connect to database
- System.out.println("Connecting to Database URL = " + url);
- db = DriverManager.getConnection(url, usr, pwd);
-
- System.out.println("Connected...Now creating a statement");
- st = db.createStatement();
-
- // Clean up the database (in case we failed earlier) then initialise
- cleanup();
-
- // Because we use LargeObjects, we must use Transactions
- db.setAutoCommit(false);
-
- // Now run tests using JDBC methods, then LargeObjects
- doexample();
-
- // Clean up the database
- cleanup();
-
- // Finally close the database
- System.out.println("Now closing the connection");
- st.close();
- db.close();
-
- }
-
- /**
- * This drops the table (if it existed). No errors are reported.
- */
- public void cleanup()
- {
- try {
- st.executeUpdate("drop table basic1");
- } catch(Exception ex) {
- // We ignore any errors here
- }
-
- try {
- st.executeUpdate("drop table basic2");
- } catch(Exception ex) {
- // We ignore any errors here
- }
- }
-
- /**
- * This performs the example
- */
- public void doexample() throws SQLException
- {
- System.out.println("\nThis test runs three Threads. Two simply insert data into a table, then\nthey perform a query. While they are running, a third thread is running,\nand it load data into, then reads from a Large Object.\n\nIf alls well, this should run without any errors. If so, we are Thread Safe.\nWhy test JDBC & LargeObject's? Because both will run over the network\nconnection, and if locking on the stream isn't done correctly, the backend\nwill get pretty confused!\n");
-
- thread3 thread3=null;
-
- try {
-
- // create the two threads
- Thread thread0 = Thread.currentThread();
- Thread thread1 = new thread1(db);
- Thread thread2 = new thread2(db);
- thread3 = new thread3(db);
-
- // now run, and wait for them
- thread1.start();
- thread2.start();
- thread3.start();
-
- // ok, I know this is bad, but it does the trick here as our main thread
- // will yield as long as either of the children are still running
- System.out.println("Waiting for threads to run");
- while(thread1.isAlive() || thread2.isAlive() || thread3.isAlive())
- thread0.yield();
-
- } finally {
- // clean up after thread3 (the finally ensures this is run even
- // if an exception is thrown inside the try { } construct)
- if(thread3 != null)
- thread3.cleanup();
- }
-
- System.out.println("No Exceptions have been thrown. This is a good omen, as it means that we are\npretty much thread safe as we can get.");
- }
-
- // This is the first thread. It's the same as the basic test
- class thread1 extends Thread
- {
- Connection c;
- Statement st;
-
- public thread1(Connection c) throws SQLException {
- this.c = c;
- st = c.createStatement();
- }
-
- public void run() {
- try {
- System.out.println("Thread 1 running...");
-
- // First we need a table to store data in
- st.executeUpdate("create table basic1 (a int2, b int2)");
-
- // Now insert some data, using the Statement
- st.executeUpdate("insert into basic1 values (1,1)");
- st.executeUpdate("insert into basic1 values (2,1)");
- st.executeUpdate("insert into basic1 values (3,1)");
-
- // For large inserts, a PreparedStatement is more efficient, because it
- // supports the idea of precompiling the SQL statement, and to store
- // directly, a Java object into any column. PostgreSQL doesnt support
- // precompiling, but does support setting a column to the value of a
- // Java object (like Date, String, etc).
- //
- // Also, this is the only way of writing dates in a datestyle independent
- // manner. (DateStyles are PostgreSQL's way of handling different methods
- // of representing dates in the Date data type.)
- PreparedStatement ps = db.prepareStatement("insert into basic1 values (?,?)");
- for(int i=2;i<2000;i++) {
- ps.setInt(1,4); // "column a" = 5
- ps.setInt(2,i); // "column b" = i
- ps.executeUpdate(); // executeUpdate because insert returns no data
-// c.commit();
- if((i%50)==0)
- DriverManager.println("Thread 1 done "+i+" inserts");
+ Connection db; // The connection to the database
+ Statement st; // Our statement to run queries with
+
+ public threadsafe(String args[]) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException
+ {
+ String url = args[0];
+ String usr = args[1];
+ String pwd = args[2];
+
+ // Load the driver
+ Class.forName("org.postgresql.Driver");
+
+ // Connect to database
+ System.out.println("Connecting to Database URL = " + url);
+ db = DriverManager.getConnection(url, usr, pwd);
+
+ System.out.println("Connected...Now creating a statement");
+ st = db.createStatement();
+
+ // Clean up the database (in case we failed earlier) then initialise
+ cleanup();
+
+ // Because we use LargeObjects, we must use Transactions
+ db.setAutoCommit(false);
+
+ // Now run tests using JDBC methods, then LargeObjects
+ doexample();
+
+ // Clean up the database
+ cleanup();
+
+ // Finally close the database
+ System.out.println("Now closing the connection");
+ st.close();
+ db.close();
+
}
- ps.close(); // Always close when we are done with it
-
- // Finally perform a query on the table
- DriverManager.println("Thread 1 performing a query");
- ResultSet rs = st.executeQuery("select a, b from basic1");
- int cnt=0;
- if(rs!=null) {
- // Now we run through the result set, printing out the result.
- // Note, we must call .next() before attempting to read any results
- while(rs.next()) {
- int a = rs.getInt("a"); // This shows how to get the value by name
- int b = rs.getInt(2); // This shows how to get the value by column
- //System.out.println(" a="+a+" b="+b);
- cnt++;
- }
- rs.close(); // again, you must close the result when done
+
+ /**
+ * This drops the table (if it existed). No errors are reported.
+ */
+ public void cleanup()
+ {
+ try
+ {
+ st.executeUpdate("drop table basic1");
+ }
+ catch (Exception ex)
+ {
+ // We ignore any errors here
+ }
+
+ try
+ {
+ st.executeUpdate("drop table basic2");
+ }
+ catch (Exception ex)
+ {
+ // We ignore any errors here
+ }
}
- DriverManager.println("Thread 1 read "+cnt+" rows");
-
- // The last thing to do is to drop the table. This is done in the
- // cleanup() method.
- System.out.println("Thread 1 finished");
- } catch(SQLException se) {
- System.err.println("Thread 1: "+se.toString());
- se.printStackTrace();
- System.exit(1);
- }
- }
- }
-
- // This is the second thread. It's the similar to the basic test, and thread1
- // except it works on another table.
- class thread2 extends Thread
- {
- Connection c;
- Statement st;
-
- public thread2(Connection c) throws SQLException {
- this.c = c;
- st = c.createStatement();
- }
-
- public void run() {
- try {
- System.out.println("Thread 2 running...");
-
- // First we need a table to store data in
- st.executeUpdate("create table basic2 (a int2, b int2)");
-
- // For large inserts, a PreparedStatement is more efficient, because it
- // supports the idea of precompiling the SQL statement, and to store
- // directly, a Java object into any column. PostgreSQL doesnt support
- // precompiling, but does support setting a column to the value of a
- // Java object (like Date, String, etc).
- //
- // Also, this is the only way of writing dates in a datestyle independent
- // manner. (DateStyles are PostgreSQL's way of handling different methods
- // of representing dates in the Date data type.)
- PreparedStatement ps = db.prepareStatement("insert into basic2 values (?,?)");
- for(int i=2;i<2000;i++) {
- ps.setInt(1,4); // "column a" = 5
- ps.setInt(2,i); // "column b" = i
- ps.executeUpdate(); // executeUpdate because insert returns no data
-// c.commit();
- if((i%50)==0)
- DriverManager.println("Thread 2 done "+i+" inserts");
+
+ /**
+ * This performs the example
+ */
+ public void doexample() throws SQLException
+ {
+ System.out.println("\nThis test runs three Threads. Two simply insert data into a table, then\nthey perform a query. While they are running, a third thread is running,\nand it load data into, then reads from a Large Object.\n\nIf alls well, this should run without any errors. If so, we are Thread Safe.\nWhy test JDBC & LargeObject's? Because both will run over the network\nconnection, and if locking on the stream isn't done correctly, the backend\nwill get pretty confused!\n");
+
+ thread3 thread3 = null;
+
+ try
+ {
+
+ // create the two threads
+ Thread thread0 = Thread.currentThread();
+ Thread thread1 = new thread1(db);
+ Thread thread2 = new thread2(db);
+ thread3 = new thread3(db);
+
+ // now run, and wait for them
+ thread1.start();
+ thread2.start();
+ thread3.start();
+
+ // ok, I know this is bad, but it does the trick here as our main thread
+ // will yield as long as either of the children are still running
+ System.out.println("Waiting for threads to run");
+ while (thread1.isAlive() || thread2.isAlive() || thread3.isAlive())
+ thread0.yield();
+
+ }
+ finally
+ {
+ // clean up after thread3 (the finally ensures this is run even
+ // if an exception is thrown inside the try { } construct)
+ if (thread3 != null)
+ thread3.cleanup();
+ }
+
+ System.out.println("No Exceptions have been thrown. This is a good omen, as it means that we are\npretty much thread safe as we can get.");
+ }
+
+ // This is the first thread. It's the same as the basic test
+ class thread1 extends Thread
+ {
+ Connection c;
+ Statement st;
+
+ public thread1(Connection c) throws SQLException
+ {
+ this.c = c;
+ st = c.createStatement();
+ }
+
+ public void run()
+ {
+ try
+ {
+ System.out.println("Thread 1 running...");
+
+ // First we need a table to store data in
+ st.executeUpdate("create table basic1 (a int2, b int2)");
+
+ // Now insert some data, using the Statement
+ st.executeUpdate("insert into basic1 values (1,1)");
+ st.executeUpdate("insert into basic1 values (2,1)");
+ st.executeUpdate("insert into basic1 values (3,1)");
+
+ // For large inserts, a PreparedStatement is more efficient, because it
+ // supports the idea of precompiling the SQL statement, and to store
+ // directly, a Java object into any column. PostgreSQL doesnt support
+ // precompiling, but does support setting a column to the value of a
+ // Java object (like Date, String, etc).
+ //
+ // Also, this is the only way of writing dates in a datestyle independent
+ // manner. (DateStyles are PostgreSQL's way of handling different methods
+ // of representing dates in the Date data type.)
+ PreparedStatement ps = db.prepareStatement("insert into basic1 values (?,?)");
+ for (int i = 2;i < 2000;i++)
+ {
+ ps.setInt(1, 4); // "column a" = 5
+ ps.setInt(2, i); // "column b" = i
+ ps.executeUpdate(); // executeUpdate because insert returns no data
+ // c.commit();
+ if ((i % 50) == 0)
+ DriverManager.println("Thread 1 done " + i + " inserts");
+ }
+ ps.close(); // Always close when we are done with it
+
+ // Finally perform a query on the table
+ DriverManager.println("Thread 1 performing a query");
+ ResultSet rs = st.executeQuery("select a, b from basic1");
+ int cnt = 0;
+ if (rs != null)
+ {
+ // Now we run through the result set, printing out the result.
+ // Note, we must call .next() before attempting to read any results
+ while (rs.next())
+ {
+ int a = rs.getInt("a"); // This shows how to get the value by name
+ int b = rs.getInt(2); // This shows how to get the value by column
+ //System.out.println(" a="+a+" b="+b);
+ cnt++;
+ }
+ rs.close(); // again, you must close the result when done
+ }
+ DriverManager.println("Thread 1 read " + cnt + " rows");
+
+ // The last thing to do is to drop the table. This is done in the
+ // cleanup() method.
+ System.out.println("Thread 1 finished");
+ }
+ catch (SQLException se)
+ {
+ System.err.println("Thread 1: " + se.toString());
+ se.printStackTrace();
+ System.exit(1);
+ }
+ }
}
- ps.close(); // Always close when we are done with it
-
- // Finally perform a query on the table
- DriverManager.println("Thread 2 performing a query");
- ResultSet rs = st.executeQuery("select * from basic2 where b>1");
- int cnt=0;
- if(rs!=null) {
- // First find out the column numbers.
- //
- // It's best to do this here, as calling the methods with the column
- // numbers actually performs this call each time they are called. This
- // really speeds things up on large queries.
- //
- int col_a = rs.findColumn("a");
- int col_b = rs.findColumn("b");
-
- // Now we run through the result set, printing out the result.
- // Again, we must call .next() before attempting to read any results
- while(rs.next()) {
- int a = rs.getInt(col_a); // This shows how to get the value by name
- int b = rs.getInt(col_b); // This shows how to get the value by column
- //System.out.println(" a="+a+" b="+b);
- cnt++;
- }
- rs.close(); // again, you must close the result when done
+
+ // This is the second thread. It's the similar to the basic test, and thread1
+ // except it works on another table.
+ class thread2 extends Thread
+ {
+ Connection c;
+ Statement st;
+
+ public thread2(Connection c) throws SQLException
+ {
+ this.c = c;
+ st = c.createStatement();
+ }
+
+ public void run()
+ {
+ try
+ {
+ System.out.println("Thread 2 running...");
+
+ // First we need a table to store data in
+ st.executeUpdate("create table basic2 (a int2, b int2)");
+
+ // For large inserts, a PreparedStatement is more efficient, because it
+ // supports the idea of precompiling the SQL statement, and to store
+ // directly, a Java object into any column. PostgreSQL doesnt support
+ // precompiling, but does support setting a column to the value of a
+ // Java object (like Date, String, etc).
+ //
+ // Also, this is the only way of writing dates in a datestyle independent
+ // manner. (DateStyles are PostgreSQL's way of handling different methods
+ // of representing dates in the Date data type.)
+ PreparedStatement ps = db.prepareStatement("insert into basic2 values (?,?)");
+ for (int i = 2;i < 2000;i++)
+ {
+ ps.setInt(1, 4); // "column a" = 5
+ ps.setInt(2, i); // "column b" = i
+ ps.executeUpdate(); // executeUpdate because insert returns no data
+ // c.commit();
+ if ((i % 50) == 0)
+ DriverManager.println("Thread 2 done " + i + " inserts");
+ }
+ ps.close(); // Always close when we are done with it
+
+ // Finally perform a query on the table
+ DriverManager.println("Thread 2 performing a query");
+ ResultSet rs = st.executeQuery("select * from basic2 where b>1");
+ int cnt = 0;
+ if (rs != null)
+ {
+ // First find out the column numbers.
+ //
+ // It's best to do this here, as calling the methods with the column
+ // numbers actually performs this call each time they are called. This
+ // really speeds things up on large queries.
+ //
+ int col_a = rs.findColumn("a");
+ int col_b = rs.findColumn("b");
+
+ // Now we run through the result set, printing out the result.
+ // Again, we must call .next() before attempting to read any results
+ while (rs.next())
+ {
+ int a = rs.getInt(col_a); // This shows how to get the value by name
+ int b = rs.getInt(col_b); // This shows how to get the value by column
+ //System.out.println(" a="+a+" b="+b);
+ cnt++;
+ }
+ rs.close(); // again, you must close the result when done
+ }
+ DriverManager.println("Thread 2 read " + cnt + " rows");
+
+ // The last thing to do is to drop the table. This is done in the
+ // cleanup() method.
+ System.out.println("Thread 2 finished");
+ }
+ catch (SQLException se)
+ {
+ System.err.println("Thread 2: " + se.toString());
+ se.printStackTrace();
+ System.exit(1);
+ }
+ }
}
- DriverManager.println("Thread 2 read "+cnt+" rows");
-
- // The last thing to do is to drop the table. This is done in the
- // cleanup() method.
- System.out.println("Thread 2 finished");
- } catch(SQLException se) {
- System.err.println("Thread 2: "+se.toString());
- se.printStackTrace();
- System.exit(1);
- }
- }
- }
-
- // This is the third thread. It loads, then reads from a LargeObject, using
- // our LargeObject api.
- //
- // The purpose of this is to test that FastPath will work in between normal
- // JDBC queries.
- class thread3 extends Thread
- {
- Connection c;
- Statement st;
- LargeObjectManager lom;
- LargeObject lo;
- int oid;
-
- public thread3(Connection c) throws SQLException {
- this.c = c;
- //st = c.createStatement();
-
- // create a blob
- lom = ((org.postgresql.Connection)c).getLargeObjectAPI();
- oid = lom.create();
- System.out.println("Thread 3 has created a blob of oid "+oid);
- }
-
- public void run() {
- try {
- System.out.println("Thread 3 running...");
-
- DriverManager.println("Thread 3: Loading data into blob "+oid);
- lo = lom.open(oid);
- FileInputStream fis = new FileInputStream("example/threadsafe.java");
- // keep the buffer size small, to allow the other thread a chance
- byte buf[] = new byte[128];
- int rc,bc=1,bs=0;
- while((rc=fis.read(buf))>0) {
- DriverManager.println("Thread 3 read block "+bc+" "+bs+" bytes");
- lo.write(buf,0,rc);
- bc++;
- bs+=rc;
+
+ // This is the third thread. It loads, then reads from a LargeObject, using
+ // our LargeObject api.
+ //
+ // The purpose of this is to test that FastPath will work in between normal
+ // JDBC queries.
+ class thread3 extends Thread
+ {
+ Connection c;
+ Statement st;
+ LargeObjectManager lom;
+ LargeObject lo;
+ int oid;
+
+ public thread3(Connection c) throws SQLException
+ {
+ this.c = c;
+ //st = c.createStatement();
+
+ // create a blob
+ lom = ((org.postgresql.Connection)c).getLargeObjectAPI();
+ oid = lom.create();
+ System.out.println("Thread 3 has created a blob of oid " + oid);
+ }
+
+ public void run()
+ {
+ try
+ {
+ System.out.println("Thread 3 running...");
+
+ DriverManager.println("Thread 3: Loading data into blob " + oid);
+ lo = lom.open(oid);
+ FileInputStream fis = new FileInputStream("example/threadsafe.java");
+ // keep the buffer size small, to allow the other thread a chance
+ byte buf[] = new byte[128];
+ int rc, bc = 1, bs = 0;
+ while ((rc = fis.read(buf)) > 0)
+ {
+ DriverManager.println("Thread 3 read block " + bc + " " + bs + " bytes");
+ lo.write(buf, 0, rc);
+ bc++;
+ bs += rc;
+ }
+ lo.close();
+ fis.close();
+
+ DriverManager.println("Thread 3: Reading blob " + oid);
+ lo = lom.open(oid);
+ bc = 0;
+ while (buf.length > 0)
+ {
+ buf = lo.read(buf.length);
+ if (buf.length > 0)
+ {
+ String s = new String(buf);
+ bc++;
+ DriverManager.println("Thread 3 block " + bc);
+ DriverManager.println("Block " + bc + " got " + s);
+ }
+ }
+ lo.close();
+
+ System.out.println("Thread 3 finished");
+ }
+ catch (Exception se)
+ {
+ System.err.println("Thread 3: " + se.toString());
+ se.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ public void cleanup() throws SQLException
+ {
+ if (lom != null && oid != 0)
+ {
+ System.out.println("Thread 3: Removing blob oid=" + oid);
+ lom.delete(oid);
+ }
+ }
}
- lo.close();
- fis.close();
-
- DriverManager.println("Thread 3: Reading blob "+oid);
- lo=lom.open(oid);
- bc=0;
- while(buf.length>0) {
- buf=lo.read(buf.length);
- if(buf.length>0) {
- String s = new String(buf);
- bc++;
- DriverManager.println("Thread 3 block "+bc);
- DriverManager.println("Block "+bc+" got "+s);
- }
+
+ /**
+ * Display some instructions on how to run the example
+ */
+ public static void instructions()
+ {
+ System.out.println("\nThis tests the thread safety of the driver.\n\nThis is done in two parts, the first with standard JDBC calls, and the\nsecond mixing FastPath and LargeObject calls with queries.\n");
+ System.out.println("Useage:\n java example.threadsafe jdbc:postgresql:database user password [debug]\n\nThe debug field can be anything. It's presence will enable DriverManager's\ndebug trace. Unless you want to see screens of items, don't put anything in\nhere.");
+ System.exit(1);
+ }
+
+ /**
+ * This little lot starts the test
+ */
+ public static void main(String args[])
+ {
+ System.out.println("PostgreSQL Thread Safety test v6.4 rev 1\n");
+
+ if (args.length < 3)
+ instructions();
+
+ // This line outputs debug information to stderr. To enable this, simply
+ // add an extra parameter to the command line
+ if (args.length > 3)
+ DriverManager.setLogStream(System.err);
+
+ // Now run the tests
+ try
+ {
+ threadsafe test = new threadsafe(args);
+ }
+ catch (Exception ex)
+ {
+ System.err.println("Exception caught.\n" + ex);
+ ex.printStackTrace();
+ }
}
- lo.close();
-
- System.out.println("Thread 3 finished");
- } catch(Exception se) {
- System.err.println("Thread 3: "+se.toString());
- se.printStackTrace();
- System.exit(1);
- }
- }
-
- public void cleanup() throws SQLException {
- if(lom!=null && oid!=0) {
- System.out.println("Thread 3: Removing blob oid="+oid);
- lom.delete(oid);
- }
- }
- }
-
- /**
- * Display some instructions on how to run the example
- */
- public static void instructions()
- {
- System.out.println("\nThis tests the thread safety of the driver.\n\nThis is done in two parts, the first with standard JDBC calls, and the\nsecond mixing FastPath and LargeObject calls with queries.\n");
- System.out.println("Useage:\n java example.threadsafe jdbc:postgresql:database user password [debug]\n\nThe debug field can be anything. It's presence will enable DriverManager's\ndebug trace. Unless you want to see screens of items, don't put anything in\nhere.");
- System.exit(1);
- }
-
- /**
- * This little lot starts the test
- */
- public static void main(String args[])
- {
- System.out.println("PostgreSQL Thread Safety test v6.4 rev 1\n");
-
- if(args.length<3)
- instructions();
-
- // This line outputs debug information to stderr. To enable this, simply
- // add an extra parameter to the command line
- if(args.length>3)
- DriverManager.setLogStream(System.err);
-
- // Now run the tests
- try {
- threadsafe test = new threadsafe(args);
- } catch(Exception ex) {
- System.err.println("Exception caught.\n"+ex);
- ex.printStackTrace();
- }
- }
}
diff --git a/src/interfaces/jdbc/org/postgresql/Connection.java b/src/interfaces/jdbc/org/postgresql/Connection.java
index 4f6aec722c8..67edcb2be43 100644
--- a/src/interfaces/jdbc/org/postgresql/Connection.java
+++ b/src/interfaces/jdbc/org/postgresql/Connection.java
@@ -11,7 +11,7 @@ import org.postgresql.util.*;
import org.postgresql.core.*;
/**
- * $Id: Connection.java,v 1.31 2001/10/16 20:05:22 barry Exp $
+ * $Id: Connection.java,v 1.32 2001/10/25 05:59:59 momjian Exp $
*
* This abstract class is used by org.postgresql.Driver to open either the JDBC1 or
* JDBC2 versions of the Connection class.
@@ -19,1062 +19,1133 @@ import org.postgresql.core.*;
*/
public abstract class Connection
{
- // This is the network stream associated with this connection
- public PG_Stream pg_stream;
-
- private String PG_HOST;
- private int PG_PORT;
- private String PG_USER;
- private String PG_PASSWORD;
- private String PG_DATABASE;
- private boolean PG_STATUS;
- private String compatible;
-
- /**
- * The encoding to use for this connection.
- */
- private Encoding encoding = Encoding.defaultEncoding();
-
- private String dbVersionNumber;
-
- public boolean CONNECTION_OK = true;
- public boolean CONNECTION_BAD = false;
-
- public boolean autoCommit = true;
- public boolean readOnly = false;
-
- public Driver this_driver;
- private String this_url;
- private String cursor = null; // The positioned update cursor name
-
- // These are new for v6.3, they determine the current protocol versions
- // supported by this version of the driver. They are defined in
- // src/include/libpq/pqcomm.h
- protected static final int PG_PROTOCOL_LATEST_MAJOR = 2;
- protected static final int PG_PROTOCOL_LATEST_MINOR = 0;
- private static final int SM_DATABASE = 64;
- private static final int SM_USER = 32;
- private static final int SM_OPTIONS = 64;
- private static final int SM_UNUSED = 64;
- private static final int SM_TTY = 64;
-
- private static final int AUTH_REQ_OK = 0;
- private static final int AUTH_REQ_KRB4 = 1;
- private static final int AUTH_REQ_KRB5 = 2;
- private static final int AUTH_REQ_PASSWORD = 3;
- private static final int AUTH_REQ_CRYPT = 4;
-
- // New for 6.3, salt value for crypt authorisation
- private String salt;
-
- // These are used to cache oids, PGTypes and SQLTypes
- private static Hashtable sqlTypeCache = new Hashtable(); // oid -> SQLType
- private static Hashtable pgTypeCache = new Hashtable(); // oid -> PGType
- private static Hashtable typeOidCache = new Hashtable(); //PGType -> oid
-
- // Now handle notices as warnings, so things like "show" now work
- public SQLWarning firstWarning = null;
-
- /**
- * Cache of the current isolation level
- */
- private int isolationLevel = java.sql.Connection.TRANSACTION_READ_COMMITTED;
-
- // The PID an cancellation key we get from the backend process
- public int pid;
- public int ckey;
-
- /**
- * This is called by Class.forName() from within org.postgresql.Driver
- */
- public Connection()
- {
- }
-
- /**
- * This method actually opens the connection. It is called by Driver.
- *
- * @param host the hostname of the database back end
- * @param port the port number of the postmaster process
- * @param info a Properties[] thing of the user and password
- * @param database the database to connect to
- * @param u the URL of the connection
- * @param d the Driver instantation of the connection
- * @return a valid connection profile
- * @exception SQLException if a database access error occurs
- */
- protected void openConnection(String host, int port, Properties info, String database, String url, Driver d) throws SQLException
- {
- // Throw an exception if the user or password properties are missing
- // This occasionally occurs when the client uses the properties version
- // of getConnection(), and is a common question on the email lists
- if(info.getProperty("user")==null)
- throw new PSQLException("postgresql.con.user");
- if(info.getProperty("password")==null)
- throw new PSQLException("postgresql.con.pass");
-
- this_driver = d;
- this_url = url;
- PG_DATABASE = database;
- PG_PASSWORD = info.getProperty("password");
- PG_USER = info.getProperty("user");
- PG_PORT = port;
- PG_HOST = host;
- PG_STATUS = CONNECTION_BAD;
- if(info.getProperty("compatible")==null) {
- compatible = d.getMajorVersion() + "." + d.getMinorVersion();
- } else {
- compatible = info.getProperty("compatible");
- }
-
- // Now make the initial connection
- try
- {
- pg_stream = new PG_Stream(host, port);
- } catch (ConnectException cex) {
- // Added by Peter Mount <peter@retep.org.uk>
- // ConnectException is thrown when the connection cannot be made.
- // we trap this an return a more meaningful message for the end user
- throw new PSQLException ("postgresql.con.refused");
- } catch (IOException e) {
- throw new PSQLException ("postgresql.con.failed",e);
- }
-
- // Now we need to construct and send a startup packet
- try
- {
- // Ver 6.3 code
- pg_stream.SendInteger(4+4+SM_DATABASE+SM_USER+SM_OPTIONS+SM_UNUSED+SM_TTY,4);
- pg_stream.SendInteger(PG_PROTOCOL_LATEST_MAJOR,2);
- pg_stream.SendInteger(PG_PROTOCOL_LATEST_MINOR,2);
- pg_stream.Send(database.getBytes(),SM_DATABASE);
-
- // This last send includes the unused fields
- pg_stream.Send(PG_USER.getBytes(),SM_USER+SM_OPTIONS+SM_UNUSED+SM_TTY);
-
- // now flush the startup packets to the backend
- pg_stream.flush();
-
- // Now get the response from the backend, either an error message
- // or an authentication request
- int areq = -1; // must have a value here
- do {
- int beresp = pg_stream.ReceiveChar();
- switch(beresp)
- {
- case 'E':
- // An error occured, so pass the error message to the
- // user.
- //
- // The most common one to be thrown here is:
- // "User authentication failed"
- //
- throw new SQLException(pg_stream.ReceiveString(encoding));
-
- case 'R':
- // Get the type of request
- areq = pg_stream.ReceiveIntegerR(4);
-
- // Get the password salt if there is one
- if(areq == AUTH_REQ_CRYPT) {
- byte[] rst = new byte[2];
- rst[0] = (byte)pg_stream.ReceiveChar();
- rst[1] = (byte)pg_stream.ReceiveChar();
- salt = new String(rst,0,2);
- DriverManager.println("Salt="+salt);
- }
-
- // now send the auth packet
- switch(areq)
- {
- case AUTH_REQ_OK:
- break;
-
- case AUTH_REQ_KRB4:
- DriverManager.println("postgresql: KRB4");
- throw new PSQLException("postgresql.con.kerb4");
-
- case AUTH_REQ_KRB5:
- DriverManager.println("postgresql: KRB5");
- throw new PSQLException("postgresql.con.kerb5");
-
- case AUTH_REQ_PASSWORD:
- DriverManager.println("postgresql: PASSWORD");
- pg_stream.SendInteger(5+PG_PASSWORD.length(),4);
- pg_stream.Send(PG_PASSWORD.getBytes());
- pg_stream.SendInteger(0,1);
- pg_stream.flush();
- break;
-
- case AUTH_REQ_CRYPT:
- DriverManager.println("postgresql: CRYPT");
- String crypted = UnixCrypt.crypt(salt,PG_PASSWORD);
- pg_stream.SendInteger(5+crypted.length(),4);
- pg_stream.Send(crypted.getBytes());
- pg_stream.SendInteger(0,1);
- pg_stream.flush();
- break;
-
- default:
- throw new PSQLException("postgresql.con.auth",new Integer(areq));
- }
- break;
-
- default:
- throw new PSQLException("postgresql.con.authfail");
- }
- } while(areq != AUTH_REQ_OK);
-
- } catch (IOException e) {
- throw new PSQLException("postgresql.con.failed",e);
- }
-
-
- // As of protocol version 2.0, we should now receive the cancellation key and the pid
- int beresp = pg_stream.ReceiveChar();
- switch(beresp) {
- case 'K':
- pid = pg_stream.ReceiveInteger(4);
- ckey = pg_stream.ReceiveInteger(4);
- break;
- case 'E':
- case 'N':
- throw new SQLException(pg_stream.ReceiveString(encoding));
- default:
- throw new PSQLException("postgresql.con.setup");
- }
-
- // Expect ReadyForQuery packet
- beresp = pg_stream.ReceiveChar();
- switch(beresp) {
- case 'Z':
- break;
- case 'E':
- case 'N':
- throw new SQLException(pg_stream.ReceiveString(encoding));
- default:
- throw new PSQLException("postgresql.con.setup");
- }
-
- firstWarning = null;
-
- // "pg_encoding_to_char(1)" will return 'EUC_JP' for a backend compiled with multibyte,
- // otherwise it's hardcoded to 'SQL_ASCII'.
- // If the backend doesn't know about multibyte we can't assume anything about the encoding
- // used, so we denote this with 'UNKNOWN'.
- //Note: begining with 7.2 we should be using pg_client_encoding() which
- //is new in 7.2. However it isn't easy to conditionally call this new
- //function, since we don't yet have the information as to what server
- //version we are talking to. Thus we will continue to call
- //getdatabaseencoding() until we drop support for 7.1 and older versions
- //or until someone comes up with a conditional way to run one or
- //the other function depending on server version that doesn't require
- //two round trips to the server per connection
-
- final String encodingQuery =
- "case when pg_encoding_to_char(1) = 'SQL_ASCII' then 'UNKNOWN' else getdatabaseencoding() end";
-
- // Set datestyle and fetch db encoding in a single call, to avoid making
- // more than one round trip to the backend during connection startup.
-
- java.sql.ResultSet resultSet =
- ExecSQL("set datestyle to 'ISO'; select version(), " + encodingQuery + ";");
-
- if (! resultSet.next()) {
- throw new PSQLException("postgresql.con.failed", "failed getting backend encoding");
- }
- String version = resultSet.getString(1);
- dbVersionNumber = extractVersionNumber(version);
-
- String dbEncoding = resultSet.getString(2);
- encoding = Encoding.getEncoding(dbEncoding, info.getProperty("charSet"));
-
- // Initialise object handling
- initObjectTypes();
-
- // Mark the connection as ok, and cleanup
- firstWarning = null;
- PG_STATUS = CONNECTION_OK;
- }
-
- // These methods used to be in the main Connection implementation. As they
- // are common to all implementations (JDBC1 or 2), they are placed here.
- // This should make it easy to maintain the two specifications.
-
- /**
- * This adds a warning to the warning chain.
- * @param msg message to add
- */
- public void addWarning(String msg)
- {
- DriverManager.println(msg);
-
- // Add the warning to the chain
- if(firstWarning!=null)
- firstWarning.setNextWarning(new SQLWarning(msg));
- else
- firstWarning = new SQLWarning(msg);
-
- // Now check for some specific messages
-
- // This is obsolete in 6.5, but I've left it in here so if we need to use this
- // technique again, we'll know where to place it.
- //
- // This is generated by the SQL "show datestyle"
- //if(msg.startsWith("NOTICE:") && msg.indexOf("DateStyle")>0) {
- //// 13 is the length off "DateStyle is "
- //msg = msg.substring(msg.indexOf("DateStyle is ")+13);
- //
- //for(int i=0;i<dateStyles.length;i+=2)
- //if(msg.startsWith(dateStyles[i]))
- //currentDateStyle=i+1; // this is the index of the format
- //}
- }
-
- /**
- * Send a query to the backend. Returns one of the ResultSet
- * objects.
- *
- * <B>Note:</B> there does not seem to be any method currently
- * in existance to return the update count.
- *
- * @param sql the SQL statement to be executed
- * @return a ResultSet holding the results
- * @exception SQLException if a database error occurs
- */
- public java.sql.ResultSet ExecSQL(String sql) throws SQLException
- {
- return ExecSQL(sql,null);
- }
-
- /**
- * Send a query to the backend. Returns one of the ResultSet
- * objects.
- *
- * <B>Note:</B> there does not seem to be any method currently
- * in existance to return the update count.
- *
- * @param sql the SQL statement to be executed
- * @param stat The Statement associated with this query (may be null)
- * @return a ResultSet holding the results
- * @exception SQLException if a database error occurs
- */
- public java.sql.ResultSet ExecSQL(String sql, java.sql.Statement stat) throws SQLException
- {
- return new QueryExecutor(sql, stat, pg_stream, this).execute();
- }
-
- /**
- * In SQL, a result table can be retrieved through a cursor that
- * is named. The current row of a result can be updated or deleted
- * using a positioned update/delete statement that references the
- * cursor name.
- *
- * We support one cursor per connection.
- *
- * setCursorName sets the cursor name.
- *
- * @param cursor the cursor name
- * @exception SQLException if a database access error occurs
- */
- public void setCursorName(String cursor) throws SQLException
- {
- this.cursor = cursor;
- }
-
- /**
- * getCursorName gets the cursor name.
- *
- * @return the current cursor name
- * @exception SQLException if a database access error occurs
- */
- public String getCursorName() throws SQLException
- {
- return cursor;
- }
-
- /**
- * We are required to bring back certain information by
- * the DatabaseMetaData class. These functions do that.
- *
- * Method getURL() brings back the URL (good job we saved it)
- *
- * @return the url
- * @exception SQLException just in case...
- */
- public String getURL() throws SQLException
- {
- return this_url;
- }
-
- /**
- * Method getUserName() brings back the User Name (again, we
- * saved it)
- *
- * @return the user name
- * @exception SQLException just in case...
- */
- public String getUserName() throws SQLException
- {
- return PG_USER;
- }
-
- /**
- * Get the character encoding to use for this connection.
- */
- public Encoding getEncoding() throws SQLException {
- return encoding;
- }
-
- /**
- * This returns the Fastpath API for the current connection.
- *
- * <p><b>NOTE:</b> This is not part of JDBC, but allows access to
- * functions on the org.postgresql backend itself.
- *
- * <p>It is primarily used by the LargeObject API
- *
- * <p>The best way to use this is as follows:
- *
- * <p><pre>
- * import org.postgresql.fastpath.*;
- * ...
- * Fastpath fp = ((org.postgresql.Connection)myconn).getFastpathAPI();
- * </pre>
- *
- * <p>where myconn is an open Connection to org.postgresql.
- *
- * @return Fastpath object allowing access to functions on the org.postgresql
- * backend.
- * @exception SQLException by Fastpath when initialising for first time
- */
- public Fastpath getFastpathAPI() throws SQLException
- {
- if(fastpath==null)
- fastpath = new Fastpath(this,pg_stream);
- return fastpath;
- }
-
- // This holds a reference to the Fastpath API if already open
- private Fastpath fastpath = null;
-
- /**
- * This returns the LargeObject API for the current connection.
- *
- * <p><b>NOTE:</b> This is not part of JDBC, but allows access to
- * functions on the org.postgresql backend itself.
- *
- * <p>The best way to use this is as follows:
- *
- * <p><pre>
- * import org.postgresql.largeobject.*;
- * ...
- * LargeObjectManager lo = ((org.postgresql.Connection)myconn).getLargeObjectAPI();
- * </pre>
- *
- * <p>where myconn is an open Connection to org.postgresql.
- *
- * @return LargeObject object that implements the API
- * @exception SQLException by LargeObject when initialising for first time
- */
- public LargeObjectManager getLargeObjectAPI() throws SQLException
- {
- if(largeobject==null)
- largeobject = new LargeObjectManager(this);
- return largeobject;
- }
-
- // This holds a reference to the LargeObject API if already open
- private LargeObjectManager largeobject = null;
-
- /**
- * This method is used internally to return an object based around
- * org.postgresql's more unique data types.
- *
- * <p>It uses an internal Hashtable to get the handling class. If the
- * type is not supported, then an instance of org.postgresql.util.PGobject
- * is returned.
- *
- * You can use the getValue() or setValue() methods to handle the returned
- * object. Custom objects can have their own methods.
- *
- * In 6.4, this is extended to use the org.postgresql.util.Serialize class to
- * allow the Serialization of Java Objects into the database without using
- * Blobs. Refer to that class for details on how this new feature works.
- *
- * @return PGobject for this type, and set to value
- * @exception SQLException if value is not correct for this type
- * @see org.postgresql.util.Serialize
- */
- public Object getObject(String type,String value) throws SQLException
- {
- try {
- Object o = objectTypes.get(type);
-
- // If o is null, then the type is unknown, so check to see if type
- // is an actual table name. If it does, see if a Class is known that
- // can handle it
- if(o == null) {
- Serialize ser = new Serialize(this,type);
- objectTypes.put(type,ser);
- return ser.fetch(Integer.parseInt(value));
- }
-
- // If o is not null, and it is a String, then its a class name that
- // extends PGobject.
- //
- // This is used to implement the org.postgresql unique types (like lseg,
- // point, etc).
- if(o instanceof String) {
- // 6.3 style extending PG_Object
- PGobject obj = null;
- obj = (PGobject)(Class.forName((String)o).newInstance());
- obj.setType(type);
- obj.setValue(value);
- return (Object)obj;
- } else {
- // If it's an object, it should be an instance of our Serialize class
- // If so, then call it's fetch method.
- if(o instanceof Serialize)
- return ((Serialize)o).fetch(Integer.parseInt(value));
- }
- } catch(SQLException sx) {
- // rethrow the exception. Done because we capture any others next
- sx.fillInStackTrace();
- throw sx;
- } catch(Exception ex) {
- throw new PSQLException("postgresql.con.creobj",type,ex);
- }
-
- // should never be reached
- return null;
- }
-
- /**
- * This stores an object into the database.
- * @param o Object to store
- * @return OID of the new rectord
- * @exception SQLException if value is not correct for this type
- * @see org.postgresql.util.Serialize
- */
- public int putObject(Object o) throws SQLException
- {
- try {
- String type = o.getClass().getName();
- Object x = objectTypes.get(type);
-
- // If x is null, then the type is unknown, so check to see if type
- // is an actual table name. If it does, see if a Class is known that
- // can handle it
- if(x == null) {
- Serialize ser = new Serialize(this,type);
- objectTypes.put(type,ser);
- return ser.store(o);
- }
-
- // If it's an object, it should be an instance of our Serialize class
- // If so, then call it's fetch method.
- if(x instanceof Serialize)
- return ((Serialize)x).store(o);
-
- // Thow an exception because the type is unknown
- throw new PSQLException("postgresql.con.strobj");
-
- } catch(SQLException sx) {
- // rethrow the exception. Done because we capture any others next
- sx.fillInStackTrace();
- throw sx;
- } catch(Exception ex) {
- throw new PSQLException("postgresql.con.strobjex",ex);
- }
- }
-
- /**
- * This allows client code to add a handler for one of org.postgresql's
- * more unique data types.
- *
- * <p><b>NOTE:</b> This is not part of JDBC, but an extension.
- *
- * <p>The best way to use this is as follows:
- *
- * <p><pre>
- * ...
- * ((org.postgresql.Connection)myconn).addDataType("mytype","my.class.name");
- * ...
- * </pre>
- *
- * <p>where myconn is an open Connection to org.postgresql.
- *
- * <p>The handling class must extend org.postgresql.util.PGobject
- *
- * @see org.postgresql.util.PGobject
- */
- public void addDataType(String type,String name)
- {
- objectTypes.put(type,name);
- }
-
- // This holds the available types
- private Hashtable objectTypes = new Hashtable();
-
- // This array contains the types that are supported as standard.
- //
- // The first entry is the types name on the database, the second
- // the full class name of the handling class.
- //
- private static final String defaultObjectTypes[][] = {
- {"box", "org.postgresql.geometric.PGbox"},
- {"circle", "org.postgresql.geometric.PGcircle"},
- {"line", "org.postgresql.geometric.PGline"},
- {"lseg", "org.postgresql.geometric.PGlseg"},
- {"path", "org.postgresql.geometric.PGpath"},
- {"point", "org.postgresql.geometric.PGpoint"},
- {"polygon", "org.postgresql.geometric.PGpolygon"},
- {"money", "org.postgresql.util.PGmoney"}
- };
-
- // This initialises the objectTypes hashtable
- private void initObjectTypes()
- {
- for(int i=0;i<defaultObjectTypes.length;i++)
- objectTypes.put(defaultObjectTypes[i][0],defaultObjectTypes[i][1]);
- }
-
- // These are required by other common classes
- public abstract java.sql.Statement createStatement() throws SQLException;
-
- /**
- * This returns a resultset. It must be overridden, so that the correct
- * version (from jdbc1 or jdbc2) are returned.
- */
- public abstract java.sql.ResultSet getResultSet(org.postgresql.Connection conn,java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount,int insertOID, boolean binaryCursor) throws SQLException;
-
- /**
- * In some cases, it is desirable to immediately release a Connection's
- * database and JDBC resources instead of waiting for them to be
- * automatically released (cant think why off the top of my head)
- *
- * <B>Note:</B> A Connection is automatically closed when it is
- * garbage collected. Certain fatal errors also result in a closed
- * connection.
- *
- * @exception SQLException if a database access error occurs
- */
- public void close() throws SQLException {
- if (pg_stream != null) {
- try {
- pg_stream.SendChar('X');
- pg_stream.flush();
- pg_stream.close();
- } catch (IOException e) {}
- pg_stream = null;
- }
- }
-
- /**
- * A driver may convert the JDBC sql grammar into its system's
- * native SQL grammar prior to sending it; nativeSQL returns the
- * native form of the statement that the driver would have sent.
- *
- * @param sql a SQL statement that may contain one or more '?'
- * parameter placeholders
- * @return the native form of this statement
- * @exception SQLException if a database access error occurs
- */
- public String nativeSQL(String sql) throws SQLException {
- return sql;
- }
-
- /**
- * The first warning reported by calls on this Connection is
- * returned.
- *
- * <B>Note:</B> Sebsequent warnings will be changed to this
- * SQLWarning
- *
- * @return the first SQLWarning or null
- * @exception SQLException if a database access error occurs
- */
- public SQLWarning getWarnings() throws SQLException {
- return firstWarning;
- }
-
- /**
- * After this call, getWarnings returns null until a new warning
- * is reported for this connection.
- *
- * @exception SQLException if a database access error occurs
- */
- public void clearWarnings() throws SQLException {
- firstWarning = null;
- }
-
-
- /**
- * You can put a connection in read-only mode as a hunt to enable
- * database optimizations
- *
- * <B>Note:</B> setReadOnly cannot be called while in the middle
- * of a transaction
- *
- * @param readOnly - true enables read-only mode; false disables it
- * @exception SQLException if a database access error occurs
- */
- public void setReadOnly(boolean readOnly) throws SQLException {
- this.readOnly = readOnly;
- }
-
- /**
- * Tests to see if the connection is in Read Only Mode. Note that
- * we cannot really put the database in read only mode, but we pretend
- * we can by returning the value of the readOnly flag
- *
- * @return true if the connection is read only
- * @exception SQLException if a database access error occurs
- */
- public boolean isReadOnly() throws SQLException {
- return readOnly;
- }
-
- /**
- * If a connection is in auto-commit mode, than all its SQL
- * statements will be executed and committed as individual
- * transactions. Otherwise, its SQL statements are grouped
- * into transactions that are terminated by either commit()
- * or rollback(). By default, new connections are in auto-
- * commit mode. The commit occurs when the statement completes
- * or the next execute occurs, whichever comes first. In the
- * case of statements returning a ResultSet, the statement
- * completes when the last row of the ResultSet has been retrieved
- * or the ResultSet has been closed. In advanced cases, a single
- * statement may return multiple results as well as output parameter
- * values. Here the commit occurs when all results and output param
- * values have been retrieved.
- *
- * @param autoCommit - true enables auto-commit; false disables it
- * @exception SQLException if a database access error occurs
- */
- public void setAutoCommit(boolean autoCommit) throws SQLException {
- if (this.autoCommit == autoCommit)
- return;
- if (autoCommit)
- ExecSQL("end");
- else {
- if (haveMinimumServerVersion("7.1")){
- ExecSQL("begin;"+getIsolationLevelSQL());
- }else{
- ExecSQL("begin");
- ExecSQL(getIsolationLevelSQL());
- }
- }
- this.autoCommit = autoCommit;
- }
-
- /**
- * gets the current auto-commit state
- *
- * @return Current state of the auto-commit mode
- * @exception SQLException (why?)
- * @see setAutoCommit
- */
- public boolean getAutoCommit() throws SQLException {
- return this.autoCommit;
- }
-
- /**
- * The method commit() makes all changes made since the previous
- * commit/rollback permanent and releases any database locks currently
- * held by the Connection. This method should only be used when
- * auto-commit has been disabled. (If autoCommit == true, then we
- * just return anyhow)
- *
- * @exception SQLException if a database access error occurs
- * @see setAutoCommit
- */
- public void commit() throws SQLException {
- if (autoCommit)
- return;
- if (haveMinimumServerVersion("7.1")){
- ExecSQL("commit;begin;"+getIsolationLevelSQL());
- }else{
- ExecSQL("commit");
- ExecSQL("begin");
- ExecSQL(getIsolationLevelSQL());
- }
- }
-
- /**
- * The method rollback() drops all changes made since the previous
- * commit/rollback and releases any database locks currently held by
- * the Connection.
- *
- * @exception SQLException if a database access error occurs
- * @see commit
- */
- public void rollback() throws SQLException {
- if (autoCommit)
- return;
- if (haveMinimumServerVersion("7.1")){
- ExecSQL("rollback; begin;"+getIsolationLevelSQL());
- }else{
- ExecSQL("rollback");
- ExecSQL("begin");
- ExecSQL(getIsolationLevelSQL());
- }
- }
-
- /**
- * Get this Connection's current transaction isolation mode.
- *
- * @return the current TRANSACTION_* mode value
- * @exception SQLException if a database access error occurs
- */
- public int getTransactionIsolation() throws SQLException {
- clearWarnings();
- ExecSQL("show xactisolevel");
-
- SQLWarning warning = getWarnings();
- if (warning != null) {
- String message = warning.getMessage();
- clearWarnings();
- if (message.indexOf("READ COMMITTED") != -1)
- return java.sql.Connection.TRANSACTION_READ_COMMITTED;
- else if (message.indexOf("READ UNCOMMITTED") != -1)
- return java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;
- else if (message.indexOf("REPEATABLE READ") != -1)
- return java.sql.Connection.TRANSACTION_REPEATABLE_READ;
- else if (message.indexOf("SERIALIZABLE") != -1)
- return java.sql.Connection.TRANSACTION_SERIALIZABLE;
- }
- return java.sql.Connection.TRANSACTION_READ_COMMITTED;
- }
-
- /**
- * You can call this method to try to change the transaction
- * isolation level using one of the TRANSACTION_* values.
- *
- * <B>Note:</B> setTransactionIsolation cannot be called while
- * in the middle of a transaction
- *
- * @param level one of the TRANSACTION_* isolation values with
- * the exception of TRANSACTION_NONE; some databases may
- * not support other values
- * @exception SQLException if a database access error occurs
- * @see java.sql.DatabaseMetaData#supportsTransactionIsolationLevel
- */
- public void setTransactionIsolation(int level) throws SQLException {
- //In 7.1 and later versions of the server it is possible using
- //the "set session" command to set this once for all future txns
- //however in 7.0 and prior versions it is necessary to set it in
- //each transaction, thus adding complexity below.
- //When we decide to drop support for servers older than 7.1
- //this can be simplified
- isolationLevel = level;
- String isolationLevelSQL;
-
- if (!haveMinimumServerVersion("7.1")) {
- isolationLevelSQL = getIsolationLevelSQL();
- } else {
- isolationLevelSQL = "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL ";
- switch(isolationLevel) {
- case java.sql.Connection.TRANSACTION_READ_COMMITTED:
- isolationLevelSQL += "READ COMMITTED";
- break;
- case java.sql.Connection.TRANSACTION_SERIALIZABLE:
- isolationLevelSQL += "SERIALIZABLE";
- break;
- default:
- throw new PSQLException("postgresql.con.isolevel",
- new Integer(isolationLevel));
- }
- }
- ExecSQL(isolationLevelSQL);
- }
-
- /**
- * Helper method used by setTransactionIsolation(), commit(), rollback()
- * and setAutoCommit(). This returns the SQL string needed to
- * set the isolation level for a transaction. In 7.1 and later it
- * is possible to set a default isolation level that applies to all
- * future transactions, this method is only necesary for 7.0 and older
- * servers, and should be removed when support for these older
- * servers are dropped
- */
- protected String getIsolationLevelSQL() throws SQLException {
- //7.1 and higher servers have a default specified so
- //no additional SQL is required to set the isolation level
- if (haveMinimumServerVersion("7.1")) {
- return "";
- }
- StringBuffer sb = new StringBuffer("SET TRANSACTION ISOLATION LEVEL");
-
- switch(isolationLevel) {
- case java.sql.Connection.TRANSACTION_READ_COMMITTED:
- sb.append(" READ COMMITTED");
- break;
-
- case java.sql.Connection.TRANSACTION_SERIALIZABLE:
- sb.append(" SERIALIZABLE");
- break;
-
- default:
- throw new PSQLException("postgresql.con.isolevel",new Integer(isolationLevel));
- }
- return sb.toString();
- }
-
- /**
- * A sub-space of this Connection's database may be selected by
- * setting a catalog name. If the driver does not support catalogs,
- * it will silently ignore this request
- *
- * @exception SQLException if a database access error occurs
- */
- public void setCatalog(String catalog) throws SQLException
- {
- //no-op
- }
-
- /**
- * Return the connections current catalog name, or null if no
- * catalog name is set, or we dont support catalogs.
- *
- * @return the current catalog name or null
- * @exception SQLException if a database access error occurs
- */
- public String getCatalog() throws SQLException
- {
- return PG_DATABASE;
- }
-
- /**
- * Overides finalize(). If called, it closes the connection.
- *
- * This was done at the request of Rachel Greenham
- * <rachel@enlarion.demon.co.uk> who hit a problem where multiple
- * clients didn't close the connection, and once a fortnight enough
- * clients were open to kill the org.postgres server.
- */
- public void finalize() throws Throwable
- {
- close();
- }
-
- private static String extractVersionNumber(String fullVersionString)
- {
- StringTokenizer versionParts = new StringTokenizer(fullVersionString);
- versionParts.nextToken(); /* "PostgreSQL" */
- return versionParts.nextToken(); /* "X.Y.Z" */
- }
-
- /**
- * Get server version number
- */
- public String getDBVersionNumber() {
- return dbVersionNumber;
- }
-
- public boolean haveMinimumServerVersion(String ver) throws SQLException
- {
- return (getDBVersionNumber().compareTo(ver) >= 0);
- }
-
- /**
- * This method returns true if the compatible level set in the connection
- * (which can be passed into the connection or specified in the URL)
- * is at least the value passed to this method. This is used to toggle
- * between different functionality as it changes across different releases
- * of the jdbc driver code. The values here are versions of the jdbc client
- * and not server versions. For example in 7.1 get/setBytes worked on
- * LargeObject values, in 7.2 these methods were changed to work on bytea
- * values. This change in functionality could be disabled by setting the
- * "compatible" level to be 7.1, in which case the driver will revert to
- * the 7.1 functionality.
- */
- public boolean haveMinimumCompatibleVersion(String ver) throws SQLException
- {
- return (compatible.compareTo(ver) >= 0);
- }
-
-
- /**
- * This returns the java.sql.Types type for a PG type oid
- *
- * @param oid PostgreSQL type oid
- * @return the java.sql.Types type
- * @exception SQLException if a database access error occurs
- */
- public int getSQLType(int oid) throws SQLException
- {
- Integer sqlType = (Integer)typeOidCache.get(new Integer(oid));
-
- // it's not in the cache, so perform a query, and add the result to the cache
- if(sqlType==null) {
- ResultSet result = (org.postgresql.ResultSet)ExecSQL("select typname from pg_type where oid = " + oid);
- if (result.getColumnCount() != 1 || result.getTupleCount() != 1)
- throw new PSQLException("postgresql.unexpected");
- result.next();
- String pgType = result.getString(1);
- Integer iOid = new Integer(oid);
- sqlType = new Integer(getSQLType(result.getString(1)));
- sqlTypeCache.put(iOid,sqlType);
- pgTypeCache.put(iOid,pgType);
- result.close();
- }
-
- return sqlType.intValue();
- }
-
- /**
- * This returns the java.sql.Types type for a PG type
- *
- * @param pgTypeName PostgreSQL type name
- * @return the java.sql.Types type
- */
- public abstract int getSQLType(String pgTypeName);
-
- /**
- * This returns the oid for a given PG data type
- * @param typeName PostgreSQL type name
- * @return PostgreSQL oid value for a field of this type
- */
- public int getOID(String typeName) throws SQLException
- {
- int oid = -1;
- if(typeName != null) {
- Integer oidValue = (Integer) typeOidCache.get(typeName);
- if(oidValue != null) {
- oid = oidValue.intValue();
- } else {
- // it's not in the cache, so perform a query, and add the result to the cache
- ResultSet result = (org.postgresql.ResultSet)ExecSQL("select oid from pg_type where typname='"
- + typeName + "'");
- if (result.getColumnCount() != 1 || result.getTupleCount() != 1)
- throw new PSQLException("postgresql.unexpected");
- result.next();
- oid = Integer.parseInt(result.getString(1));
- typeOidCache.put(typeName, new Integer(oid));
- result.close();
- }
- }
- return oid;
- }
-
- /**
- * We also need to get the PG type name as returned by the back end.
- *
- * @return the String representation of the type of this field
- * @exception SQLException if a database access error occurs
- */
- public String getPGType(int oid) throws SQLException
- {
- String pgType = (String) pgTypeCache.get(new Integer(oid));
- if(pgType == null) {
- getSQLType(oid);
- pgType = (String) pgTypeCache.get(new Integer(oid));
- }
- return pgType;
- }
+ // This is the network stream associated with this connection
+ public PG_Stream pg_stream;
+
+ private String PG_HOST;
+ private int PG_PORT;
+ private String PG_USER;
+ private String PG_PASSWORD;
+ private String PG_DATABASE;
+ private boolean PG_STATUS;
+ private String compatible;
+
+ /**
+ * The encoding to use for this connection.
+ */
+ private Encoding encoding = Encoding.defaultEncoding();
+
+ private String dbVersionNumber;
+
+ public boolean CONNECTION_OK = true;
+ public boolean CONNECTION_BAD = false;
+
+ public boolean autoCommit = true;
+ public boolean readOnly = false;
+
+ public Driver this_driver;
+ private String this_url;
+ private String cursor = null; // The positioned update cursor name
+
+ // These are new for v6.3, they determine the current protocol versions
+ // supported by this version of the driver. They are defined in
+ // src/include/libpq/pqcomm.h
+ protected static final int PG_PROTOCOL_LATEST_MAJOR = 2;
+ protected static final int PG_PROTOCOL_LATEST_MINOR = 0;
+ private static final int SM_DATABASE = 64;
+ private static final int SM_USER = 32;
+ private static final int SM_OPTIONS = 64;
+ private static final int SM_UNUSED = 64;
+ private static final int SM_TTY = 64;
+
+ private static final int AUTH_REQ_OK = 0;
+ private static final int AUTH_REQ_KRB4 = 1;
+ private static final int AUTH_REQ_KRB5 = 2;
+ private static final int AUTH_REQ_PASSWORD = 3;
+ private static final int AUTH_REQ_CRYPT = 4;
+
+ // New for 6.3, salt value for crypt authorisation
+ private String salt;
+
+ // These are used to cache oids, PGTypes and SQLTypes
+ private static Hashtable sqlTypeCache = new Hashtable(); // oid -> SQLType
+ private static Hashtable pgTypeCache = new Hashtable(); // oid -> PGType
+ private static Hashtable typeOidCache = new Hashtable(); //PGType -> oid
+
+ // Now handle notices as warnings, so things like "show" now work
+ public SQLWarning firstWarning = null;
+
+ /**
+ * Cache of the current isolation level
+ */
+ private int isolationLevel = java.sql.Connection.TRANSACTION_READ_COMMITTED;
+
+ // The PID an cancellation key we get from the backend process
+ public int pid;
+ public int ckey;
+
+ /**
+ * This is called by Class.forName() from within org.postgresql.Driver
+ */
+ public Connection()
+ {}
+
+ /**
+ * This method actually opens the connection. It is called by Driver.
+ *
+ * @param host the hostname of the database back end
+ * @param port the port number of the postmaster process
+ * @param info a Properties[] thing of the user and password
+ * @param database the database to connect to
+ * @param u the URL of the connection
+ * @param d the Driver instantation of the connection
+ * @return a valid connection profile
+ * @exception SQLException if a database access error occurs
+ */
+ protected void openConnection(String host, int port, Properties info, String database, String url, Driver d) throws SQLException
+ {
+ // Throw an exception if the user or password properties are missing
+ // This occasionally occurs when the client uses the properties version
+ // of getConnection(), and is a common question on the email lists
+ if (info.getProperty("user") == null)
+ throw new PSQLException("postgresql.con.user");
+ if (info.getProperty("password") == null)
+ throw new PSQLException("postgresql.con.pass");
+
+ this_driver = d;
+ this_url = url;
+ PG_DATABASE = database;
+ PG_PASSWORD = info.getProperty("password");
+ PG_USER = info.getProperty("user");
+ PG_PORT = port;
+ PG_HOST = host;
+ PG_STATUS = CONNECTION_BAD;
+ if (info.getProperty("compatible") == null)
+ {
+ compatible = d.getMajorVersion() + "." + d.getMinorVersion();
+ }
+ else
+ {
+ compatible = info.getProperty("compatible");
+ }
+
+ // Now make the initial connection
+ try
+ {
+ pg_stream = new PG_Stream(host, port);
+ }
+ catch (ConnectException cex)
+ {
+ // Added by Peter Mount <peter@retep.org.uk>
+ // ConnectException is thrown when the connection cannot be made.
+ // we trap this an return a more meaningful message for the end user
+ throw new PSQLException ("postgresql.con.refused");
+ }
+ catch (IOException e)
+ {
+ throw new PSQLException ("postgresql.con.failed", e);
+ }
+
+ // Now we need to construct and send a startup packet
+ try
+ {
+ // Ver 6.3 code
+ pg_stream.SendInteger(4 + 4 + SM_DATABASE + SM_USER + SM_OPTIONS + SM_UNUSED + SM_TTY, 4);
+ pg_stream.SendInteger(PG_PROTOCOL_LATEST_MAJOR, 2);
+ pg_stream.SendInteger(PG_PROTOCOL_LATEST_MINOR, 2);
+ pg_stream.Send(database.getBytes(), SM_DATABASE);
+
+ // This last send includes the unused fields
+ pg_stream.Send(PG_USER.getBytes(), SM_USER + SM_OPTIONS + SM_UNUSED + SM_TTY);
+
+ // now flush the startup packets to the backend
+ pg_stream.flush();
+
+ // Now get the response from the backend, either an error message
+ // or an authentication request
+ int areq = -1; // must have a value here
+ do
+ {
+ int beresp = pg_stream.ReceiveChar();
+ switch (beresp)
+ {
+ case 'E':
+ // An error occured, so pass the error message to the
+ // user.
+ //
+ // The most common one to be thrown here is:
+ // "User authentication failed"
+ //
+ throw new SQLException(pg_stream.ReceiveString(encoding));
+
+ case 'R':
+ // Get the type of request
+ areq = pg_stream.ReceiveIntegerR(4);
+
+ // Get the password salt if there is one
+ if (areq == AUTH_REQ_CRYPT)
+ {
+ byte[] rst = new byte[2];
+ rst[0] = (byte)pg_stream.ReceiveChar();
+ rst[1] = (byte)pg_stream.ReceiveChar();
+ salt = new String(rst, 0, 2);
+ DriverManager.println("Salt=" + salt);
+ }
+
+ // now send the auth packet
+ switch (areq)
+ {
+ case AUTH_REQ_OK:
+ break;
+
+ case AUTH_REQ_KRB4:
+ DriverManager.println("postgresql: KRB4");
+ throw new PSQLException("postgresql.con.kerb4");
+
+ case AUTH_REQ_KRB5:
+ DriverManager.println("postgresql: KRB5");
+ throw new PSQLException("postgresql.con.kerb5");
+
+ case AUTH_REQ_PASSWORD:
+ DriverManager.println("postgresql: PASSWORD");
+ pg_stream.SendInteger(5 + PG_PASSWORD.length(), 4);
+ pg_stream.Send(PG_PASSWORD.getBytes());
+ pg_stream.SendInteger(0, 1);
+ pg_stream.flush();
+ break;
+
+ case AUTH_REQ_CRYPT:
+ DriverManager.println("postgresql: CRYPT");
+ String crypted = UnixCrypt.crypt(salt, PG_PASSWORD);
+ pg_stream.SendInteger(5 + crypted.length(), 4);
+ pg_stream.Send(crypted.getBytes());
+ pg_stream.SendInteger(0, 1);
+ pg_stream.flush();
+ break;
+
+ default:
+ throw new PSQLException("postgresql.con.auth", new Integer(areq));
+ }
+ break;
+
+ default:
+ throw new PSQLException("postgresql.con.authfail");
+ }
+ }
+ while (areq != AUTH_REQ_OK);
+
+ }
+ catch (IOException e)
+ {
+ throw new PSQLException("postgresql.con.failed", e);
+ }
+
+
+ // As of protocol version 2.0, we should now receive the cancellation key and the pid
+ int beresp = pg_stream.ReceiveChar();
+ switch (beresp)
+ {
+ case 'K':
+ pid = pg_stream.ReceiveInteger(4);
+ ckey = pg_stream.ReceiveInteger(4);
+ break;
+ case 'E':
+ case 'N':
+ throw new SQLException(pg_stream.ReceiveString(encoding));
+ default:
+ throw new PSQLException("postgresql.con.setup");
+ }
+
+ // Expect ReadyForQuery packet
+ beresp = pg_stream.ReceiveChar();
+ switch (beresp)
+ {
+ case 'Z':
+ break;
+ case 'E':
+ case 'N':
+ throw new SQLException(pg_stream.ReceiveString(encoding));
+ default:
+ throw new PSQLException("postgresql.con.setup");
+ }
+
+ firstWarning = null;
+
+ // "pg_encoding_to_char(1)" will return 'EUC_JP' for a backend compiled with multibyte,
+ // otherwise it's hardcoded to 'SQL_ASCII'.
+ // If the backend doesn't know about multibyte we can't assume anything about the encoding
+ // used, so we denote this with 'UNKNOWN'.
+ //Note: begining with 7.2 we should be using pg_client_encoding() which
+ //is new in 7.2. However it isn't easy to conditionally call this new
+ //function, since we don't yet have the information as to what server
+ //version we are talking to. Thus we will continue to call
+ //getdatabaseencoding() until we drop support for 7.1 and older versions
+ //or until someone comes up with a conditional way to run one or
+ //the other function depending on server version that doesn't require
+ //two round trips to the server per connection
+
+ final String encodingQuery =
+ "case when pg_encoding_to_char(1) = 'SQL_ASCII' then 'UNKNOWN' else getdatabaseencoding() end";
+
+ // Set datestyle and fetch db encoding in a single call, to avoid making
+ // more than one round trip to the backend during connection startup.
+
+ java.sql.ResultSet resultSet =
+ ExecSQL("set datestyle to 'ISO'; select version(), " + encodingQuery + ";");
+
+ if (! resultSet.next())
+ {
+ throw new PSQLException("postgresql.con.failed", "failed getting backend encoding");
+ }
+ String version = resultSet.getString(1);
+ dbVersionNumber = extractVersionNumber(version);
+
+ String dbEncoding = resultSet.getString(2);
+ encoding = Encoding.getEncoding(dbEncoding, info.getProperty("charSet"));
+
+ // Initialise object handling
+ initObjectTypes();
+
+ // Mark the connection as ok, and cleanup
+ firstWarning = null;
+ PG_STATUS = CONNECTION_OK;
+ }
+
+ // These methods used to be in the main Connection implementation. As they
+ // are common to all implementations (JDBC1 or 2), they are placed here.
+ // This should make it easy to maintain the two specifications.
+
+ /**
+ * This adds a warning to the warning chain.
+ * @param msg message to add
+ */
+ public void addWarning(String msg)
+ {
+ DriverManager.println(msg);
+
+ // Add the warning to the chain
+ if (firstWarning != null)
+ firstWarning.setNextWarning(new SQLWarning(msg));
+ else
+ firstWarning = new SQLWarning(msg);
+
+ // Now check for some specific messages
+
+ // This is obsolete in 6.5, but I've left it in here so if we need to use this
+ // technique again, we'll know where to place it.
+ //
+ // This is generated by the SQL "show datestyle"
+ //if(msg.startsWith("NOTICE:") && msg.indexOf("DateStyle")>0) {
+ //// 13 is the length off "DateStyle is "
+ //msg = msg.substring(msg.indexOf("DateStyle is ")+13);
+ //
+ //for(int i=0;i<dateStyles.length;i+=2)
+ //if(msg.startsWith(dateStyles[i]))
+ //currentDateStyle=i+1; // this is the index of the format
+ //}
+ }
+
+ /**
+ * Send a query to the backend. Returns one of the ResultSet
+ * objects.
+ *
+ * <B>Note:</B> there does not seem to be any method currently
+ * in existance to return the update count.
+ *
+ * @param sql the SQL statement to be executed
+ * @return a ResultSet holding the results
+ * @exception SQLException if a database error occurs
+ */
+ public java.sql.ResultSet ExecSQL(String sql) throws SQLException
+ {
+ return ExecSQL(sql, null);
+ }
+
+ /**
+ * Send a query to the backend. Returns one of the ResultSet
+ * objects.
+ *
+ * <B>Note:</B> there does not seem to be any method currently
+ * in existance to return the update count.
+ *
+ * @param sql the SQL statement to be executed
+ * @param stat The Statement associated with this query (may be null)
+ * @return a ResultSet holding the results
+ * @exception SQLException if a database error occurs
+ */
+ public java.sql.ResultSet ExecSQL(String sql, java.sql.Statement stat) throws SQLException
+ {
+ return new QueryExecutor(sql, stat, pg_stream, this).execute();
+ }
+
+ /**
+ * In SQL, a result table can be retrieved through a cursor that
+ * is named. The current row of a result can be updated or deleted
+ * using a positioned update/delete statement that references the
+ * cursor name.
+ *
+ * We support one cursor per connection.
+ *
+ * setCursorName sets the cursor name.
+ *
+ * @param cursor the cursor name
+ * @exception SQLException if a database access error occurs
+ */
+ public void setCursorName(String cursor) throws SQLException
+ {
+ this.cursor = cursor;
+ }
+
+ /**
+ * getCursorName gets the cursor name.
+ *
+ * @return the current cursor name
+ * @exception SQLException if a database access error occurs
+ */
+ public String getCursorName() throws SQLException
+ {
+ return cursor;
+ }
+
+ /**
+ * We are required to bring back certain information by
+ * the DatabaseMetaData class. These functions do that.
+ *
+ * Method getURL() brings back the URL (good job we saved it)
+ *
+ * @return the url
+ * @exception SQLException just in case...
+ */
+ public String getURL() throws SQLException
+ {
+ return this_url;
+ }
+
+ /**
+ * Method getUserName() brings back the User Name (again, we
+ * saved it)
+ *
+ * @return the user name
+ * @exception SQLException just in case...
+ */
+ public String getUserName() throws SQLException
+ {
+ return PG_USER;
+ }
+
+ /**
+ * Get the character encoding to use for this connection.
+ */
+ public Encoding getEncoding() throws SQLException
+ {
+ return encoding;
+ }
+
+ /**
+ * This returns the Fastpath API for the current connection.
+ *
+ * <p><b>NOTE:</b> This is not part of JDBC, but allows access to
+ * functions on the org.postgresql backend itself.
+ *
+ * <p>It is primarily used by the LargeObject API
+ *
+ * <p>The best way to use this is as follows:
+ *
+ * <p><pre>
+ * import org.postgresql.fastpath.*;
+ * ...
+ * Fastpath fp = ((org.postgresql.Connection)myconn).getFastpathAPI();
+ * </pre>
+ *
+ * <p>where myconn is an open Connection to org.postgresql.
+ *
+ * @return Fastpath object allowing access to functions on the org.postgresql
+ * backend.
+ * @exception SQLException by Fastpath when initialising for first time
+ */
+ public Fastpath getFastpathAPI() throws SQLException
+ {
+ if (fastpath == null)
+ fastpath = new Fastpath(this, pg_stream);
+ return fastpath;
+ }
+
+ // This holds a reference to the Fastpath API if already open
+ private Fastpath fastpath = null;
+
+ /**
+ * This returns the LargeObject API for the current connection.
+ *
+ * <p><b>NOTE:</b> This is not part of JDBC, but allows access to
+ * functions on the org.postgresql backend itself.
+ *
+ * <p>The best way to use this is as follows:
+ *
+ * <p><pre>
+ * import org.postgresql.largeobject.*;
+ * ...
+ * LargeObjectManager lo = ((org.postgresql.Connection)myconn).getLargeObjectAPI();
+ * </pre>
+ *
+ * <p>where myconn is an open Connection to org.postgresql.
+ *
+ * @return LargeObject object that implements the API
+ * @exception SQLException by LargeObject when initialising for first time
+ */
+ public LargeObjectManager getLargeObjectAPI() throws SQLException
+ {
+ if (largeobject == null)
+ largeobject = new LargeObjectManager(this);
+ return largeobject;
+ }
+
+ // This holds a reference to the LargeObject API if already open
+ private LargeObjectManager largeobject = null;
+
+ /**
+ * This method is used internally to return an object based around
+ * org.postgresql's more unique data types.
+ *
+ * <p>It uses an internal Hashtable to get the handling class. If the
+ * type is not supported, then an instance of org.postgresql.util.PGobject
+ * is returned.
+ *
+ * You can use the getValue() or setValue() methods to handle the returned
+ * object. Custom objects can have their own methods.
+ *
+ * In 6.4, this is extended to use the org.postgresql.util.Serialize class to
+ * allow the Serialization of Java Objects into the database without using
+ * Blobs. Refer to that class for details on how this new feature works.
+ *
+ * @return PGobject for this type, and set to value
+ * @exception SQLException if value is not correct for this type
+ * @see org.postgresql.util.Serialize
+ */
+ public Object getObject(String type, String value) throws SQLException
+ {
+ try
+ {
+ Object o = objectTypes.get(type);
+
+ // If o is null, then the type is unknown, so check to see if type
+ // is an actual table name. If it does, see if a Class is known that
+ // can handle it
+ if (o == null)
+ {
+ Serialize ser = new Serialize(this, type);
+ objectTypes.put(type, ser);
+ return ser.fetch(Integer.parseInt(value));
+ }
+
+ // If o is not null, and it is a String, then its a class name that
+ // extends PGobject.
+ //
+ // This is used to implement the org.postgresql unique types (like lseg,
+ // point, etc).
+ if (o instanceof String)
+ {
+ // 6.3 style extending PG_Object
+ PGobject obj = null;
+ obj = (PGobject)(Class.forName((String)o).newInstance());
+ obj.setType(type);
+ obj.setValue(value);
+ return (Object)obj;
+ }
+ else
+ {
+ // If it's an object, it should be an instance of our Serialize class
+ // If so, then call it's fetch method.
+ if (o instanceof Serialize)
+ return ((Serialize)o).fetch(Integer.parseInt(value));
+ }
+ }
+ catch (SQLException sx)
+ {
+ // rethrow the exception. Done because we capture any others next
+ sx.fillInStackTrace();
+ throw sx;
+ }
+ catch (Exception ex)
+ {
+ throw new PSQLException("postgresql.con.creobj", type, ex);
+ }
+
+ // should never be reached
+ return null;
+ }
+
+ /**
+ * This stores an object into the database.
+ * @param o Object to store
+ * @return OID of the new rectord
+ * @exception SQLException if value is not correct for this type
+ * @see org.postgresql.util.Serialize
+ */
+ public int putObject(Object o) throws SQLException
+ {
+ try
+ {
+ String type = o.getClass().getName();
+ Object x = objectTypes.get(type);
+
+ // If x is null, then the type is unknown, so check to see if type
+ // is an actual table name. If it does, see if a Class is known that
+ // can handle it
+ if (x == null)
+ {
+ Serialize ser = new Serialize(this, type);
+ objectTypes.put(type, ser);
+ return ser.store(o);
+ }
+
+ // If it's an object, it should be an instance of our Serialize class
+ // If so, then call it's fetch method.
+ if (x instanceof Serialize)
+ return ((Serialize)x).store(o);
+
+ // Thow an exception because the type is unknown
+ throw new PSQLException("postgresql.con.strobj");
+
+ }
+ catch (SQLException sx)
+ {
+ // rethrow the exception. Done because we capture any others next
+ sx.fillInStackTrace();
+ throw sx;
+ }
+ catch (Exception ex)
+ {
+ throw new PSQLException("postgresql.con.strobjex", ex);
+ }
+ }
+
+ /**
+ * This allows client code to add a handler for one of org.postgresql's
+ * more unique data types.
+ *
+ * <p><b>NOTE:</b> This is not part of JDBC, but an extension.
+ *
+ * <p>The best way to use this is as follows:
+ *
+ * <p><pre>
+ * ...
+ * ((org.postgresql.Connection)myconn).addDataType("mytype","my.class.name");
+ * ...
+ * </pre>
+ *
+ * <p>where myconn is an open Connection to org.postgresql.
+ *
+ * <p>The handling class must extend org.postgresql.util.PGobject
+ *
+ * @see org.postgresql.util.PGobject
+ */
+ public void addDataType(String type, String name)
+ {
+ objectTypes.put(type, name);
+ }
+
+ // This holds the available types
+ private Hashtable objectTypes = new Hashtable();
+
+ // This array contains the types that are supported as standard.
+ //
+ // The first entry is the types name on the database, the second
+ // the full class name of the handling class.
+ //
+ private static final String defaultObjectTypes[][] = {
+ {"box", "org.postgresql.geometric.PGbox"},
+ {"circle", "org.postgresql.geometric.PGcircle"},
+ {"line", "org.postgresql.geometric.PGline"},
+ {"lseg", "org.postgresql.geometric.PGlseg"},
+ {"path", "org.postgresql.geometric.PGpath"},
+ {"point", "org.postgresql.geometric.PGpoint"},
+ {"polygon", "org.postgresql.geometric.PGpolygon"},
+ {"money", "org.postgresql.util.PGmoney"}
+ };
+
+ // This initialises the objectTypes hashtable
+ private void initObjectTypes()
+ {
+ for (int i = 0;i < defaultObjectTypes.length;i++)
+ objectTypes.put(defaultObjectTypes[i][0], defaultObjectTypes[i][1]);
+ }
+
+ // These are required by other common classes
+ public abstract java.sql.Statement createStatement() throws SQLException;
+
+ /**
+ * This returns a resultset. It must be overridden, so that the correct
+ * version (from jdbc1 or jdbc2) are returned.
+ */
+ public abstract java.sql.ResultSet getResultSet(org.postgresql.Connection conn, java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount, int insertOID, boolean binaryCursor) throws SQLException;
+
+ /**
+ * In some cases, it is desirable to immediately release a Connection's
+ * database and JDBC resources instead of waiting for them to be
+ * automatically released (cant think why off the top of my head)
+ *
+ * <B>Note:</B> A Connection is automatically closed when it is
+ * garbage collected. Certain fatal errors also result in a closed
+ * connection.
+ *
+ * @exception SQLException if a database access error occurs
+ */
+ public void close() throws SQLException
+ {
+ if (pg_stream != null)
+ {
+ try
+ {
+ pg_stream.SendChar('X');
+ pg_stream.flush();
+ pg_stream.close();
+ }
+ catch (IOException e)
+ {}
+ pg_stream = null;
+ }
+ }
+
+ /**
+ * A driver may convert the JDBC sql grammar into its system's
+ * native SQL grammar prior to sending it; nativeSQL returns the
+ * native form of the statement that the driver would have sent.
+ *
+ * @param sql a SQL statement that may contain one or more '?'
+ * parameter placeholders
+ * @return the native form of this statement
+ * @exception SQLException if a database access error occurs
+ */
+ public String nativeSQL(String sql) throws SQLException
+ {
+ return sql;
+ }
+
+ /**
+ * The first warning reported by calls on this Connection is
+ * returned.
+ *
+ * <B>Note:</B> Sebsequent warnings will be changed to this
+ * SQLWarning
+ *
+ * @return the first SQLWarning or null
+ * @exception SQLException if a database access error occurs
+ */
+ public SQLWarning getWarnings() throws SQLException
+ {
+ return firstWarning;
+ }
+
+ /**
+ * After this call, getWarnings returns null until a new warning
+ * is reported for this connection.
+ *
+ * @exception SQLException if a database access error occurs
+ */
+ public void clearWarnings() throws SQLException
+ {
+ firstWarning = null;
+ }
+
+
+ /**
+ * You can put a connection in read-only mode as a hunt to enable
+ * database optimizations
+ *
+ * <B>Note:</B> setReadOnly cannot be called while in the middle
+ * of a transaction
+ *
+ * @param readOnly - true enables read-only mode; false disables it
+ * @exception SQLException if a database access error occurs
+ */
+ public void setReadOnly(boolean readOnly) throws SQLException
+ {
+ this.readOnly = readOnly;
+ }
+
+ /**
+ * Tests to see if the connection is in Read Only Mode. Note that
+ * we cannot really put the database in read only mode, but we pretend
+ * we can by returning the value of the readOnly flag
+ *
+ * @return true if the connection is read only
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean isReadOnly() throws SQLException
+ {
+ return readOnly;
+ }
+
+ /**
+ * If a connection is in auto-commit mode, than all its SQL
+ * statements will be executed and committed as individual
+ * transactions. Otherwise, its SQL statements are grouped
+ * into transactions that are terminated by either commit()
+ * or rollback(). By default, new connections are in auto-
+ * commit mode. The commit occurs when the statement completes
+ * or the next execute occurs, whichever comes first. In the
+ * case of statements returning a ResultSet, the statement
+ * completes when the last row of the ResultSet has been retrieved
+ * or the ResultSet has been closed. In advanced cases, a single
+ * statement may return multiple results as well as output parameter
+ * values. Here the commit occurs when all results and output param
+ * values have been retrieved.
+ *
+ * @param autoCommit - true enables auto-commit; false disables it
+ * @exception SQLException if a database access error occurs
+ */
+ public void setAutoCommit(boolean autoCommit) throws SQLException
+ {
+ if (this.autoCommit == autoCommit)
+ return ;
+ if (autoCommit)
+ ExecSQL("end");
+ else
+ {
+ if (haveMinimumServerVersion("7.1"))
+ {
+ ExecSQL("begin;" + getIsolationLevelSQL());
+ }
+ else
+ {
+ ExecSQL("begin");
+ ExecSQL(getIsolationLevelSQL());
+ }
+ }
+ this.autoCommit = autoCommit;
+ }
+
+ /**
+ * gets the current auto-commit state
+ *
+ * @return Current state of the auto-commit mode
+ * @exception SQLException (why?)
+ * @see setAutoCommit
+ */
+ public boolean getAutoCommit() throws SQLException
+ {
+ return this.autoCommit;
+ }
+
+ /**
+ * The method commit() makes all changes made since the previous
+ * commit/rollback permanent and releases any database locks currently
+ * held by the Connection. This method should only be used when
+ * auto-commit has been disabled. (If autoCommit == true, then we
+ * just return anyhow)
+ *
+ * @exception SQLException if a database access error occurs
+ * @see setAutoCommit
+ */
+ public void commit() throws SQLException
+ {
+ if (autoCommit)
+ return ;
+ if (haveMinimumServerVersion("7.1"))
+ {
+ ExecSQL("commit;begin;" + getIsolationLevelSQL());
+ }
+ else
+ {
+ ExecSQL("commit");
+ ExecSQL("begin");
+ ExecSQL(getIsolationLevelSQL());
+ }
+ }
+
+ /**
+ * The method rollback() drops all changes made since the previous
+ * commit/rollback and releases any database locks currently held by
+ * the Connection.
+ *
+ * @exception SQLException if a database access error occurs
+ * @see commit
+ */
+ public void rollback() throws SQLException
+ {
+ if (autoCommit)
+ return ;
+ if (haveMinimumServerVersion("7.1"))
+ {
+ ExecSQL("rollback; begin;" + getIsolationLevelSQL());
+ }
+ else
+ {
+ ExecSQL("rollback");
+ ExecSQL("begin");
+ ExecSQL(getIsolationLevelSQL());
+ }
+ }
+
+ /**
+ * Get this Connection's current transaction isolation mode.
+ *
+ * @return the current TRANSACTION_* mode value
+ * @exception SQLException if a database access error occurs
+ */
+ public int getTransactionIsolation() throws SQLException
+ {
+ clearWarnings();
+ ExecSQL("show xactisolevel");
+
+ SQLWarning warning = getWarnings();
+ if (warning != null)
+ {
+ String message = warning.getMessage();
+ clearWarnings();
+ if (message.indexOf("READ COMMITTED") != -1)
+ return java.sql.Connection.TRANSACTION_READ_COMMITTED;
+ else if (message.indexOf("READ UNCOMMITTED") != -1)
+ return java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;
+ else if (message.indexOf("REPEATABLE READ") != -1)
+ return java.sql.Connection.TRANSACTION_REPEATABLE_READ;
+ else if (message.indexOf("SERIALIZABLE") != -1)
+ return java.sql.Connection.TRANSACTION_SERIALIZABLE;
+ }
+ return java.sql.Connection.TRANSACTION_READ_COMMITTED;
+ }
+
+ /**
+ * You can call this method to try to change the transaction
+ * isolation level using one of the TRANSACTION_* values.
+ *
+ * <B>Note:</B> setTransactionIsolation cannot be called while
+ * in the middle of a transaction
+ *
+ * @param level one of the TRANSACTION_* isolation values with
+ * the exception of TRANSACTION_NONE; some databases may
+ * not support other values
+ * @exception SQLException if a database access error occurs
+ * @see java.sql.DatabaseMetaData#supportsTransactionIsolationLevel
+ */
+ public void setTransactionIsolation(int level) throws SQLException
+ {
+ //In 7.1 and later versions of the server it is possible using
+ //the "set session" command to set this once for all future txns
+ //however in 7.0 and prior versions it is necessary to set it in
+ //each transaction, thus adding complexity below.
+ //When we decide to drop support for servers older than 7.1
+ //this can be simplified
+ isolationLevel = level;
+ String isolationLevelSQL;
+
+ if (!haveMinimumServerVersion("7.1"))
+ {
+ isolationLevelSQL = getIsolationLevelSQL();
+ }
+ else
+ {
+ isolationLevelSQL = "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL ";
+ switch (isolationLevel)
+ {
+ case java.sql.Connection.TRANSACTION_READ_COMMITTED:
+ isolationLevelSQL += "READ COMMITTED";
+ break;
+ case java.sql.Connection.TRANSACTION_SERIALIZABLE:
+ isolationLevelSQL += "SERIALIZABLE";
+ break;
+ default:
+ throw new PSQLException("postgresql.con.isolevel",
+ new Integer(isolationLevel));
+ }
+ }
+ ExecSQL(isolationLevelSQL);
+ }
+
+ /**
+ * Helper method used by setTransactionIsolation(), commit(), rollback()
+ * and setAutoCommit(). This returns the SQL string needed to
+ * set the isolation level for a transaction. In 7.1 and later it
+ * is possible to set a default isolation level that applies to all
+ * future transactions, this method is only necesary for 7.0 and older
+ * servers, and should be removed when support for these older
+ * servers are dropped
+ */
+ protected String getIsolationLevelSQL() throws SQLException
+ {
+ //7.1 and higher servers have a default specified so
+ //no additional SQL is required to set the isolation level
+ if (haveMinimumServerVersion("7.1"))
+ {
+ return "";
+ }
+ StringBuffer sb = new StringBuffer("SET TRANSACTION ISOLATION LEVEL");
+
+ switch (isolationLevel)
+ {
+ case java.sql.Connection.TRANSACTION_READ_COMMITTED:
+ sb.append(" READ COMMITTED");
+ break;
+
+ case java.sql.Connection.TRANSACTION_SERIALIZABLE:
+ sb.append(" SERIALIZABLE");
+ break;
+
+ default:
+ throw new PSQLException("postgresql.con.isolevel", new Integer(isolationLevel));
+ }
+ return sb.toString();
+ }
+
+ /**
+ * A sub-space of this Connection's database may be selected by
+ * setting a catalog name. If the driver does not support catalogs,
+ * it will silently ignore this request
+ *
+ * @exception SQLException if a database access error occurs
+ */
+ public void setCatalog(String catalog) throws SQLException
+ {
+ //no-op
+ }
+
+ /**
+ * Return the connections current catalog name, or null if no
+ * catalog name is set, or we dont support catalogs.
+ *
+ * @return the current catalog name or null
+ * @exception SQLException if a database access error occurs
+ */
+ public String getCatalog() throws SQLException
+ {
+ return PG_DATABASE;
+ }
+
+ /**
+ * Overides finalize(). If called, it closes the connection.
+ *
+ * This was done at the request of Rachel Greenham
+ * <rachel@enlarion.demon.co.uk> who hit a problem where multiple
+ * clients didn't close the connection, and once a fortnight enough
+ * clients were open to kill the org.postgres server.
+ */
+ public void finalize() throws Throwable
+ {
+ close();
+ }
+
+ private static String extractVersionNumber(String fullVersionString)
+ {
+ StringTokenizer versionParts = new StringTokenizer(fullVersionString);
+ versionParts.nextToken(); /* "PostgreSQL" */
+ return versionParts.nextToken(); /* "X.Y.Z" */
+ }
+
+ /**
+ * Get server version number
+ */
+ public String getDBVersionNumber()
+ {
+ return dbVersionNumber;
+ }
+
+ public boolean haveMinimumServerVersion(String ver) throws SQLException
+ {
+ return (getDBVersionNumber().compareTo(ver) >= 0);
+ }
+
+ /**
+ * This method returns true if the compatible level set in the connection
+ * (which can be passed into the connection or specified in the URL)
+ * is at least the value passed to this method. This is used to toggle
+ * between different functionality as it changes across different releases
+ * of the jdbc driver code. The values here are versions of the jdbc client
+ * and not server versions. For example in 7.1 get/setBytes worked on
+ * LargeObject values, in 7.2 these methods were changed to work on bytea
+ * values. This change in functionality could be disabled by setting the
+ * "compatible" level to be 7.1, in which case the driver will revert to
+ * the 7.1 functionality.
+ */
+ public boolean haveMinimumCompatibleVersion(String ver) throws SQLException
+ {
+ return (compatible.compareTo(ver) >= 0);
+ }
+
+
+ /**
+ * This returns the java.sql.Types type for a PG type oid
+ *
+ * @param oid PostgreSQL type oid
+ * @return the java.sql.Types type
+ * @exception SQLException if a database access error occurs
+ */
+ public int getSQLType(int oid) throws SQLException
+ {
+ Integer sqlType = (Integer)typeOidCache.get(new Integer(oid));
+
+ // it's not in the cache, so perform a query, and add the result to the cache
+ if (sqlType == null)
+ {
+ ResultSet result = (org.postgresql.ResultSet)ExecSQL("select typname from pg_type where oid = " + oid);
+ if (result.getColumnCount() != 1 || result.getTupleCount() != 1)
+ throw new PSQLException("postgresql.unexpected");
+ result.next();
+ String pgType = result.getString(1);
+ Integer iOid = new Integer(oid);
+ sqlType = new Integer(getSQLType(result.getString(1)));
+ sqlTypeCache.put(iOid, sqlType);
+ pgTypeCache.put(iOid, pgType);
+ result.close();
+ }
+
+ return sqlType.intValue();
+ }
+
+ /**
+ * This returns the java.sql.Types type for a PG type
+ *
+ * @param pgTypeName PostgreSQL type name
+ * @return the java.sql.Types type
+ */
+ public abstract int getSQLType(String pgTypeName);
+
+ /**
+ * This returns the oid for a given PG data type
+ * @param typeName PostgreSQL type name
+ * @return PostgreSQL oid value for a field of this type
+ */
+ public int getOID(String typeName) throws SQLException
+ {
+ int oid = -1;
+ if (typeName != null)
+ {
+ Integer oidValue = (Integer) typeOidCache.get(typeName);
+ if (oidValue != null)
+ {
+ oid = oidValue.intValue();
+ }
+ else
+ {
+ // it's not in the cache, so perform a query, and add the result to the cache
+ ResultSet result = (org.postgresql.ResultSet)ExecSQL("select oid from pg_type where typname='"
+ + typeName + "'");
+ if (result.getColumnCount() != 1 || result.getTupleCount() != 1)
+ throw new PSQLException("postgresql.unexpected");
+ result.next();
+ oid = Integer.parseInt(result.getString(1));
+ typeOidCache.put(typeName, new Integer(oid));
+ result.close();
+ }
+ }
+ return oid;
+ }
+
+ /**
+ * We also need to get the PG type name as returned by the back end.
+ *
+ * @return the String representation of the type of this field
+ * @exception SQLException if a database access error occurs
+ */
+ public String getPGType(int oid) throws SQLException
+ {
+ String pgType = (String) pgTypeCache.get(new Integer(oid));
+ if (pgType == null)
+ {
+ getSQLType(oid);
+ pgType = (String) pgTypeCache.get(new Integer(oid));
+ }
+ return pgType;
+ }
}
diff --git a/src/interfaces/jdbc/org/postgresql/Field.java b/src/interfaces/jdbc/org/postgresql/Field.java
index 1bbc272aa80..88507311c97 100644
--- a/src/interfaces/jdbc/org/postgresql/Field.java
+++ b/src/interfaces/jdbc/org/postgresql/Field.java
@@ -12,96 +12,96 @@ import org.postgresql.util.*;
*/
public class Field
{
- private int length; // Internal Length of this field
- private int oid; // OID of the type
- private int mod; // type modifier of this field
- private String name; // Name of this field
+ private int length; // Internal Length of this field
+ private int oid; // OID of the type
+ private int mod; // type modifier of this field
+ private String name; // Name of this field
- private Connection conn; // Connection Instantation
+ private Connection conn; // Connection Instantation
- /**
- * Construct a field based on the information fed to it.
- *
- * @param conn the connection this field came from
- * @param name the name of the field
- * @param oid the OID of the field
- * @param len the length of the field
- */
- public Field(Connection conn, String name, int oid, int length,int mod)
- {
- this.conn = conn;
- this.name = name;
- this.oid = oid;
- this.length = length;
- this.mod = mod;
- }
+ /**
+ * Construct a field based on the information fed to it.
+ *
+ * @param conn the connection this field came from
+ * @param name the name of the field
+ * @param oid the OID of the field
+ * @param len the length of the field
+ */
+ public Field(Connection conn, String name, int oid, int length, int mod)
+ {
+ this.conn = conn;
+ this.name = name;
+ this.oid = oid;
+ this.length = length;
+ this.mod = mod;
+ }
- /**
- * Constructor without mod parameter.
- *
- * @param conn the connection this field came from
- * @param name the name of the field
- * @param oid the OID of the field
- * @param len the length of the field
- */
- public Field(Connection conn, String name, int oid, int length)
- {
- this(conn,name,oid,length,0);
- }
+ /**
+ * Constructor without mod parameter.
+ *
+ * @param conn the connection this field came from
+ * @param name the name of the field
+ * @param oid the OID of the field
+ * @param len the length of the field
+ */
+ public Field(Connection conn, String name, int oid, int length)
+ {
+ this(conn, name, oid, length, 0);
+ }
- /**
- * @return the oid of this Field's data type
- */
- public int getOID()
- {
- return oid;
- }
+ /**
+ * @return the oid of this Field's data type
+ */
+ public int getOID()
+ {
+ return oid;
+ }
- /**
- * @return the mod of this Field's data type
- */
- public int getMod()
- {
- return mod;
- }
+ /**
+ * @return the mod of this Field's data type
+ */
+ public int getMod()
+ {
+ return mod;
+ }
- /**
- * @return the name of this Field's data type
- */
- public String getName()
- {
- return name;
- }
+ /**
+ * @return the name of this Field's data type
+ */
+ public String getName()
+ {
+ return name;
+ }
- /**
- * @return the length of this Field's data type
- */
- public int getLength()
- {
- return length;
- }
+ /**
+ * @return the length of this Field's data type
+ */
+ public int getLength()
+ {
+ return length;
+ }
- /**
- * We also need to get the PG type name as returned by the back end.
- *
- * @return the String representation of the PG type of this field
- * @exception SQLException if a database access error occurs
- */
- public String getPGType() throws SQLException
- {
- return conn.getPGType(oid);
- }
+ /**
+ * We also need to get the PG type name as returned by the back end.
+ *
+ * @return the String representation of the PG type of this field
+ * @exception SQLException if a database access error occurs
+ */
+ public String getPGType() throws SQLException
+ {
+ return conn.getPGType(oid);
+ }
- /**
- * We also need to get the java.sql.types type.
- *
- * @return the int representation of the java.sql.types type of this field
- * @exception SQLException if a database access error occurs
- */
- public int getSQLType() throws SQLException
- {
- return conn.getSQLType(oid);
- }
+ /**
+ * We also need to get the java.sql.types type.
+ *
+ * @return the int representation of the java.sql.types type of this field
+ * @exception SQLException if a database access error occurs
+ */
+ public int getSQLType() throws SQLException
+ {
+ return conn.getSQLType(oid);
+ }
}
diff --git a/src/interfaces/jdbc/org/postgresql/PG_Stream.java b/src/interfaces/jdbc/org/postgresql/PG_Stream.java
index 71a090b0d48..049b4c57828 100644
--- a/src/interfaces/jdbc/org/postgresql/PG_Stream.java
+++ b/src/interfaces/jdbc/org/postgresql/PG_Stream.java
@@ -10,345 +10,366 @@ import org.postgresql.core.*;
import org.postgresql.util.*;
/**
- * $Id: PG_Stream.java,v 1.13 2001/08/26 17:08:48 momjian Exp $
+ * $Id: PG_Stream.java,v 1.14 2001/10/25 05:59:59 momjian Exp $
*
* This class is used by Connection & PGlobj for communicating with the
* backend.
*
* @see java.sql.Connection
*/
-// This class handles all the Streamed I/O for a org.postgresql connection
+// This class handles all the Streamed I/O for a org.postgresql connection
public class PG_Stream
{
- private Socket connection;
- private InputStream pg_input;
- private BufferedOutputStream pg_output;
- private byte[] byte_buf = new byte[8*1024];
+ private Socket connection;
+ private InputStream pg_input;
+ private BufferedOutputStream pg_output;
+ private byte[] byte_buf = new byte[8*1024];
- BytePoolDim1 bytePoolDim1 = new BytePoolDim1();
- BytePoolDim2 bytePoolDim2 = new BytePoolDim2();
+ BytePoolDim1 bytePoolDim1 = new BytePoolDim1();
+ BytePoolDim2 bytePoolDim2 = new BytePoolDim2();
- /**
- * Constructor: Connect to the PostgreSQL back end and return
- * a stream connection.
- *
- * @param host the hostname to connect to
- * @param port the port number that the postmaster is sitting on
- * @exception IOException if an IOException occurs below it.
- */
- public PG_Stream(String host, int port) throws IOException
- {
- connection = new Socket(host, port);
+ /**
+ * Constructor: Connect to the PostgreSQL back end and return
+ * a stream connection.
+ *
+ * @param host the hostname to connect to
+ * @param port the port number that the postmaster is sitting on
+ * @exception IOException if an IOException occurs below it.
+ */
+ public PG_Stream(String host, int port) throws IOException
+ {
+ connection = new Socket(host, port);
- // Submitted by Jason Venner <jason@idiom.com> adds a 10x speed
- // improvement on FreeBSD machines (caused by a bug in their TCP Stack)
- connection.setTcpNoDelay(true);
+ // Submitted by Jason Venner <jason@idiom.com> adds a 10x speed
+ // improvement on FreeBSD machines (caused by a bug in their TCP Stack)
+ connection.setTcpNoDelay(true);
- // Buffer sizes submitted by Sverre H Huseby <sverrehu@online.no>
- pg_input = new BufferedInputStream(connection.getInputStream(), 8192);
- pg_output = new BufferedOutputStream(connection.getOutputStream(), 8192);
- }
+ // Buffer sizes submitted by Sverre H Huseby <sverrehu@online.no>
+ pg_input = new BufferedInputStream(connection.getInputStream(), 8192);
+ pg_output = new BufferedOutputStream(connection.getOutputStream(), 8192);
+ }
- /**
- * Sends a single character to the back end
- *
- * @param val the character to be sent
- * @exception IOException if an I/O error occurs
- */
- public void SendChar(int val) throws IOException
- {
- pg_output.write((byte)val);
- }
+ /**
+ * Sends a single character to the back end
+ *
+ * @param val the character to be sent
+ * @exception IOException if an I/O error occurs
+ */
+ public void SendChar(int val) throws IOException
+ {
+ pg_output.write((byte)val);
+ }
- /**
- * Sends an integer to the back end
- *
- * @param val the integer to be sent
- * @param siz the length of the integer in bytes (size of structure)
- * @exception IOException if an I/O error occurs
- */
- public void SendInteger(int val, int siz) throws IOException
- {
- byte[] buf = bytePoolDim1.allocByte(siz);
+ /**
+ * Sends an integer to the back end
+ *
+ * @param val the integer to be sent
+ * @param siz the length of the integer in bytes (size of structure)
+ * @exception IOException if an I/O error occurs
+ */
+ public void SendInteger(int val, int siz) throws IOException
+ {
+ byte[] buf = bytePoolDim1.allocByte(siz);
- while (siz-- > 0)
- {
- buf[siz] = (byte)(val & 0xff);
- val >>= 8;
- }
- Send(buf);
- }
+ while (siz-- > 0)
+ {
+ buf[siz] = (byte)(val & 0xff);
+ val >>= 8;
+ }
+ Send(buf);
+ }
- /**
- * Send an array of bytes to the backend
- *
- * @param buf The array of bytes to be sent
- * @exception IOException if an I/O error occurs
- */
- public void Send(byte buf[]) throws IOException
- {
- pg_output.write(buf);
- }
+ /**
+ * Send an array of bytes to the backend
+ *
+ * @param buf The array of bytes to be sent
+ * @exception IOException if an I/O error occurs
+ */
+ public void Send(byte buf[]) throws IOException
+ {
+ pg_output.write(buf);
+ }
- /**
- * Send an exact array of bytes to the backend - if the length
- * has not been reached, send nulls until it has.
- *
- * @param buf the array of bytes to be sent
- * @param siz the number of bytes to be sent
- * @exception IOException if an I/O error occurs
- */
- public void Send(byte buf[], int siz) throws IOException
- {
- Send(buf,0,siz);
- }
+ /**
+ * Send an exact array of bytes to the backend - if the length
+ * has not been reached, send nulls until it has.
+ *
+ * @param buf the array of bytes to be sent
+ * @param siz the number of bytes to be sent
+ * @exception IOException if an I/O error occurs
+ */
+ public void Send(byte buf[], int siz) throws IOException
+ {
+ Send(buf, 0, siz);
+ }
- /**
- * Send an exact array of bytes to the backend - if the length
- * has not been reached, send nulls until it has.
- *
- * @param buf the array of bytes to be sent
- * @param off offset in the array to start sending from
- * @param siz the number of bytes to be sent
- * @exception IOException if an I/O error occurs
- */
- public void Send(byte buf[], int off, int siz) throws IOException
- {
- int i;
+ /**
+ * Send an exact array of bytes to the backend - if the length
+ * has not been reached, send nulls until it has.
+ *
+ * @param buf the array of bytes to be sent
+ * @param off offset in the array to start sending from
+ * @param siz the number of bytes to be sent
+ * @exception IOException if an I/O error occurs
+ */
+ public void Send(byte buf[], int off, int siz) throws IOException
+ {
+ int i;
- pg_output.write(buf, off, ((buf.length-off) < siz ? (buf.length-off) : siz));
- if((buf.length-off) < siz)
- {
- for (i = buf.length-off ; i < siz ; ++i)
- {
- pg_output.write(0);
- }
- }
- }
+ pg_output.write(buf, off, ((buf.length - off) < siz ? (buf.length - off) : siz));
+ if ((buf.length - off) < siz)
+ {
+ for (i = buf.length - off ; i < siz ; ++i)
+ {
+ pg_output.write(0);
+ }
+ }
+ }
- /**
- * Receives a single character from the backend
- *
- * @return the character received
- * @exception SQLException if an I/O Error returns
- */
- public int ReceiveChar() throws SQLException
- {
- int c = 0;
+ /**
+ * Receives a single character from the backend
+ *
+ * @return the character received
+ * @exception SQLException if an I/O Error returns
+ */
+ public int ReceiveChar() throws SQLException
+ {
+ int c = 0;
- try
- {
- c = pg_input.read();
- if (c < 0) throw new PSQLException("postgresql.stream.eof");
- } catch (IOException e) {
- throw new PSQLException("postgresql.stream.ioerror",e);
- }
- return c;
- }
+ try
+ {
+ c = pg_input.read();
+ if (c < 0)
+ throw new PSQLException("postgresql.stream.eof");
+ }
+ catch (IOException e)
+ {
+ throw new PSQLException("postgresql.stream.ioerror", e);
+ }
+ return c;
+ }
- /**
- * Receives an integer from the backend
- *
- * @param siz length of the integer in bytes
- * @return the integer received from the backend
- * @exception SQLException if an I/O error occurs
- */
- public int ReceiveInteger(int siz) throws SQLException
- {
- int n = 0;
+ /**
+ * Receives an integer from the backend
+ *
+ * @param siz length of the integer in bytes
+ * @return the integer received from the backend
+ * @exception SQLException if an I/O error occurs
+ */
+ public int ReceiveInteger(int siz) throws SQLException
+ {
+ int n = 0;
- try
- {
- for (int i = 0 ; i < siz ; i++)
- {
- int b = pg_input.read();
+ try
+ {
+ for (int i = 0 ; i < siz ; i++)
+ {
+ int b = pg_input.read();
- if (b < 0)
- throw new PSQLException("postgresql.stream.eof");
- n = n | (b << (8 * i)) ;
- }
- } catch (IOException e) {
- throw new PSQLException("postgresql.stream.ioerror",e);
- }
- return n;
- }
+ if (b < 0)
+ throw new PSQLException("postgresql.stream.eof");
+ n = n | (b << (8 * i)) ;
+ }
+ }
+ catch (IOException e)
+ {
+ throw new PSQLException("postgresql.stream.ioerror", e);
+ }
+ return n;
+ }
- /**
- * Receives an integer from the backend
- *
- * @param siz length of the integer in bytes
- * @return the integer received from the backend
- * @exception SQLException if an I/O error occurs
- */
- public int ReceiveIntegerR(int siz) throws SQLException
- {
- int n = 0;
+ /**
+ * Receives an integer from the backend
+ *
+ * @param siz length of the integer in bytes
+ * @return the integer received from the backend
+ * @exception SQLException if an I/O error occurs
+ */
+ public int ReceiveIntegerR(int siz) throws SQLException
+ {
+ int n = 0;
- try
- {
- for (int i = 0 ; i < siz ; i++)
- {
- int b = pg_input.read();
+ try
+ {
+ for (int i = 0 ; i < siz ; i++)
+ {
+ int b = pg_input.read();
- if (b < 0)
- throw new PSQLException("postgresql.stream.eof");
- n = b | (n << 8);
- }
- } catch (IOException e) {
- throw new PSQLException("postgresql.stream.ioerror",e);
- }
- return n;
- }
+ if (b < 0)
+ throw new PSQLException("postgresql.stream.eof");
+ n = b | (n << 8);
+ }
+ }
+ catch (IOException e)
+ {
+ throw new PSQLException("postgresql.stream.ioerror", e);
+ }
+ return n;
+ }
- /**
- * Receives a null-terminated string from the backend. If we don't see a
- * null, then we assume something has gone wrong.
- *
- * @param encoding the charset encoding to use.
- * @return string from back end
- * @exception SQLException if an I/O error occurs, or end of file
- */
- public String ReceiveString(Encoding encoding)
- throws SQLException
- {
- int s = 0;
- byte[] rst = byte_buf;
- try {
- int buflen = rst.length;
- boolean done = false;
- while (!done) {
- while (s < buflen) {
- int c = pg_input.read();
- if (c < 0)
- throw new PSQLException("postgresql.stream.eof");
- else if (c == 0) {
- rst[s] = 0;
- done = true;
- break;
- } else {
- rst[s++] = (byte)c;
- }
- if (s >= buflen) { // Grow the buffer
- buflen = (int)(buflen*2); // 100% bigger
- byte[] newrst = new byte[buflen];
- System.arraycopy(rst, 0, newrst, 0, s);
- rst = newrst;
- }
- }
- }
- } catch (IOException e) {
- throw new PSQLException("postgresql.stream.ioerror",e);
- }
- return encoding.decode(rst, 0, s);
- }
+ /**
+ * Receives a null-terminated string from the backend. If we don't see a
+ * null, then we assume something has gone wrong.
+ *
+ * @param encoding the charset encoding to use.
+ * @return string from back end
+ * @exception SQLException if an I/O error occurs, or end of file
+ */
+ public String ReceiveString(Encoding encoding)
+ throws SQLException
+ {
+ int s = 0;
+ byte[] rst = byte_buf;
+ try
+ {
+ int buflen = rst.length;
+ boolean done = false;
+ while (!done)
+ {
+ while (s < buflen)
+ {
+ int c = pg_input.read();
+ if (c < 0)
+ throw new PSQLException("postgresql.stream.eof");
+ else if (c == 0)
+ {
+ rst[s] = 0;
+ done = true;
+ break;
+ }
+ else
+ {
+ rst[s++] = (byte)c;
+ }
+ if (s >= buflen)
+ { // Grow the buffer
+ buflen = (int)(buflen * 2); // 100% bigger
+ byte[] newrst = new byte[buflen];
+ System.arraycopy(rst, 0, newrst, 0, s);
+ rst = newrst;
+ }
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ throw new PSQLException("postgresql.stream.ioerror", e);
+ }
+ return encoding.decode(rst, 0, s);
+ }
- /**
- * Read a tuple from the back end. A tuple is a two dimensional
- * array of bytes
- *
- * @param nf the number of fields expected
- * @param bin true if the tuple is a binary tuple
- * @return null if the current response has no more tuples, otherwise
- * an array of strings
- * @exception SQLException if a data I/O error occurs
- */
- public byte[][] ReceiveTuple(int nf, boolean bin) throws SQLException
- {
- int i, bim = (nf + 7)/8;
- byte[] bitmask = Receive(bim);
- byte[][] answer = bytePoolDim2.allocByte(nf);
+ /**
+ * Read a tuple from the back end. A tuple is a two dimensional
+ * array of bytes
+ *
+ * @param nf the number of fields expected
+ * @param bin true if the tuple is a binary tuple
+ * @return null if the current response has no more tuples, otherwise
+ * an array of strings
+ * @exception SQLException if a data I/O error occurs
+ */
+ public byte[][] ReceiveTuple(int nf, boolean bin) throws SQLException
+ {
+ int i, bim = (nf + 7) / 8;
+ byte[] bitmask = Receive(bim);
+ byte[][] answer = bytePoolDim2.allocByte(nf);
- int whichbit = 0x80;
- int whichbyte = 0;
+ int whichbit = 0x80;
+ int whichbyte = 0;
- for (i = 0 ; i < nf ; ++i)
- {
- boolean isNull = ((bitmask[whichbyte] & whichbit) == 0);
- whichbit >>= 1;
- if (whichbit == 0)
- {
- ++whichbyte;
- whichbit = 0x80;
- }
- if (isNull)
- answer[i] = null;
- else
- {
- int len = ReceiveIntegerR(4);
- if (!bin)
- len -= 4;
- if (len < 0)
- len = 0;
- answer[i] = Receive(len);
- }
- }
- return answer;
- }
+ for (i = 0 ; i < nf ; ++i)
+ {
+ boolean isNull = ((bitmask[whichbyte] & whichbit) == 0);
+ whichbit >>= 1;
+ if (whichbit == 0)
+ {
+ ++whichbyte;
+ whichbit = 0x80;
+ }
+ if (isNull)
+ answer[i] = null;
+ else
+ {
+ int len = ReceiveIntegerR(4);
+ if (!bin)
+ len -= 4;
+ if (len < 0)
+ len = 0;
+ answer[i] = Receive(len);
+ }
+ }
+ return answer;
+ }
- /**
- * Reads in a given number of bytes from the backend
- *
- * @param siz number of bytes to read
- * @return array of bytes received
- * @exception SQLException if a data I/O error occurs
- */
- private byte[] Receive(int siz) throws SQLException
- {
- byte[] answer = bytePoolDim1.allocByte(siz);
- Receive(answer,0,siz);
- return answer;
- }
+ /**
+ * Reads in a given number of bytes from the backend
+ *
+ * @param siz number of bytes to read
+ * @return array of bytes received
+ * @exception SQLException if a data I/O error occurs
+ */
+ private byte[] Receive(int siz) throws SQLException
+ {
+ byte[] answer = bytePoolDim1.allocByte(siz);
+ Receive(answer, 0, siz);
+ return answer;
+ }
- /**
- * Reads in a given number of bytes from the backend
- *
- * @param buf buffer to store result
- * @param off offset in buffer
- * @param siz number of bytes to read
- * @exception SQLException if a data I/O error occurs
- */
- public void Receive(byte[] b,int off,int siz) throws SQLException
- {
- int s = 0;
+ /**
+ * Reads in a given number of bytes from the backend
+ *
+ * @param buf buffer to store result
+ * @param off offset in buffer
+ * @param siz number of bytes to read
+ * @exception SQLException if a data I/O error occurs
+ */
+ public void Receive(byte[] b, int off, int siz) throws SQLException
+ {
+ int s = 0;
- try
- {
- while (s < siz)
- {
- int w = pg_input.read(b, off+s, siz - s);
- if (w < 0)
- throw new PSQLException("postgresql.stream.eof");
- s += w;
- }
- } catch (IOException e) {
- throw new PSQLException("postgresql.stream.ioerror",e);
- }
- }
+ try
+ {
+ while (s < siz)
+ {
+ int w = pg_input.read(b, off + s, siz - s);
+ if (w < 0)
+ throw new PSQLException("postgresql.stream.eof");
+ s += w;
+ }
+ }
+ catch (IOException e)
+ {
+ throw new PSQLException("postgresql.stream.ioerror", e);
+ }
+ }
- /**
- * This flushes any pending output to the backend. It is used primarily
- * by the Fastpath code.
- * @exception SQLException if an I/O error occurs
- */
- public void flush() throws SQLException
- {
- try {
- pg_output.flush();
- } catch (IOException e) {
- throw new PSQLException("postgresql.stream.flush",e);
- }
- }
+ /**
+ * This flushes any pending output to the backend. It is used primarily
+ * by the Fastpath code.
+ * @exception SQLException if an I/O error occurs
+ */
+ public void flush() throws SQLException
+ {
+ try
+ {
+ pg_output.flush();
+ }
+ catch (IOException e)
+ {
+ throw new PSQLException("postgresql.stream.flush", e);
+ }
+ }
- /**
- * Closes the connection
- *
- * @exception IOException if a IO Error occurs
- */
- public void close() throws IOException
- {
- pg_output.close();
- pg_input.close();
- connection.close();
- }
+ /**
+ * Closes the connection
+ *
+ * @exception IOException if a IO Error occurs
+ */
+ public void close() throws IOException
+ {
+ pg_output.close();
+ pg_input.close();
+ connection.close();
+ }
}
diff --git a/src/interfaces/jdbc/org/postgresql/PostgresqlDataSource.java b/src/interfaces/jdbc/org/postgresql/PostgresqlDataSource.java
index 62ee87ae9f8..26dddfbf3de 100644
--- a/src/interfaces/jdbc/org/postgresql/PostgresqlDataSource.java
+++ b/src/interfaces/jdbc/org/postgresql/PostgresqlDataSource.java
@@ -1,47 +1,47 @@
/**
- * Redistribution and use of this software and associated documentation
- * ("Software"), with or without modification, are permitted provided
- * that the following conditions are met:
- *
- * 1. Redistributions of source code must retain copyright
- * statements and notices. Redistributions must also contain a
- * copy of this document.
- *
- * 2. Redistributions in binary form must reproduce the
- * above copyright notice, this list of conditions and the
- * following disclaimer in the documentation and/or other
- * materials provided with the distribution.
- *
- * 3. The name "Exolab" must not be used to endorse or promote
- * products derived from this Software without prior written
- * permission of Exoffice Technologies. For written permission,
- * please contact info@exolab.org.
- *
- * 4. Products derived from this Software may not be called "Exolab"
- * nor may "Exolab" appear in their names without prior written
- * permission of Exoffice Technologies. Exolab is a registered
- * trademark of Exoffice Technologies.
- *
- * 5. Due credit should be given to the Exolab Project
- * (http://www.exolab.org/).
- *
- * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
- * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Copyright 1999 (C) Exoffice Technologies Inc. All Rights Reserved.
- *
- * $Id: PostgresqlDataSource.java,v 1.2 2000/11/10 22:06:26 momjian Exp $
- */
+* Redistribution and use of this software and associated documentation
+* ("Software"), with or without modification, are permitted provided
+* that the following conditions are met:
+*
+* 1. Redistributions of source code must retain copyright
+* statements and notices. Redistributions must also contain a
+* copy of this document.
+*
+* 2. Redistributions in binary form must reproduce the
+* above copyright notice, this list of conditions and the
+* following disclaimer in the documentation and/or other
+* materials provided with the distribution.
+*
+* 3. The name "Exolab" must not be used to endorse or promote
+* products derived from this Software without prior written
+* permission of Exoffice Technologies. For written permission,
+* please contact info@exolab.org.
+*
+* 4. Products derived from this Software may not be called "Exolab"
+* nor may "Exolab" appear in their names without prior written
+* permission of Exoffice Technologies. Exolab is a registered
+* trademark of Exoffice Technologies.
+*
+* 5. Due credit should be given to the Exolab Project
+* (http://www.exolab.org/).
+*
+* THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
+* ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
+* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+* EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Copyright 1999 (C) Exoffice Technologies Inc. All Rights Reserved.
+*
+* $Id: PostgresqlDataSource.java,v 1.3 2001/10/25 05:59:59 momjian Exp $
+*/
package org.postgresql;
@@ -79,13 +79,13 @@ import org.postgresql.xa.XADataSourceImpl;
* <p>
* The supported data source properties are:
* <pre>
- * description (optional)
- * databaseName (required)
- * loginTimeout (optional)
- * user (optional)
- * password (optional)
- * serverName (optional)
- * portNumber (optional)
+ * description (optional)
+ * databaseName (required)
+ * loginTimeout (optional)
+ * user (optional)
+ * password (optional)
+ * serverName (optional)
+ * portNumber (optional)
* transactionTimeout (optional for XA connections)
* </pre>
* This data source may be serialized and stored in a JNDI
@@ -93,7 +93,7 @@ import org.postgresql.xa.XADataSourceImpl;
* register it with JNDI:
* <pre>
* PostgresqlDataSource ds;
- * InitialContext ctx;
+ * InitialContext ctx;
*
* ds = new PostgresqlDataSource();
* ds.setDatabaseName( "test" );
@@ -105,9 +105,9 @@ import org.postgresql.xa.XADataSourceImpl;
* Example for obtaining the data source from JNDI and
* opening a new connections:
* <pre>
- * InitialContext ctx;
- * DataSource ds;
- *
+ * InitialContext ctx;
+ * DataSource ds;
+ *
* ctx = new InitialContext();
* ds = (DataSource) ctx.lookup( "/comp/jdbc/test" );
* ds.getConnection();
@@ -121,482 +121,502 @@ import org.postgresql.xa.XADataSourceImpl;
* @see Connection
*/
public class PostgresqlDataSource
- extends XADataSourceImpl
- implements DataSource, Referenceable,
- ObjectFactory, Serializable
+ extends XADataSourceImpl
+ implements DataSource, Referenceable,
+ ObjectFactory, Serializable
{
- /**
- * Holds the timeout for opening a new connection, specified
- * in seconds. The default is obtained from the JDBC driver.
- */
- private int _loginTimeout;
+ /**
+ * Holds the timeout for opening a new connection, specified
+ * in seconds. The default is obtained from the JDBC driver.
+ */
+ private int _loginTimeout;
- /**
- * Holds the user's account name.
- */
- private String _user;
+ /**
+ * Holds the user's account name.
+ */
+ private String _user;
- /**
- * Holds the database password.
- */
- private String _password;
+ /**
+ * Holds the database password.
+ */
+ private String _password;
- /**
- * Holds the name of the particular database on the server.
- */
- private String _databaseName;
+ /**
+ * Holds the name of the particular database on the server.
+ */
+ private String _databaseName;
- /**
- * Description of this datasource.
- */
- private String _description = "PostgreSQL DataSource";
+ /**
+ * Description of this datasource.
+ */
+ private String _description = "PostgreSQL DataSource";
- /**
- * Holds the database server name. If null, this is
- * assumed to be the localhost.
- */
- private String _serverName;
+ /**
+ * Holds the database server name. If null, this is
+ * assumed to be the localhost.
+ */
+ private String _serverName;
- /**
- * Holds the port number where a server is listening.
- * The default value will open a connection with an
- * unspecified port.
- */
- private int _portNumber = DEFAULT_PORT;
+ /**
+ * Holds the port number where a server is listening.
+ * The default value will open a connection with an
+ * unspecified port.
+ */
+ private int _portNumber = DEFAULT_PORT;
- /**
- * The default port number. Since we open the connection
- * without specifying the port if it's the default one,
- * this value can be meaningless.
- */
- private static final int DEFAULT_PORT = 0;
+ /**
+ * The default port number. Since we open the connection
+ * without specifying the port if it's the default one,
+ * this value can be meaningless.
+ */
+ private static final int DEFAULT_PORT = 0;
- /**
- * Holds the log writer to which all messages should be
- * printed. The default writer is obtained from the driver
- * manager, but it can be specified at the datasource level
- * and will be passed to the driver. May be null.
- */
- private transient PrintWriter _logWriter;
+ /**
+ * Holds the log writer to which all messages should be
+ * printed. The default writer is obtained from the driver
+ * manager, but it can be specified at the datasource level
+ * and will be passed to the driver. May be null.
+ */
+ private transient PrintWriter _logWriter;
- /**
- * Each datasource maintains it's own driver, in case of
- * driver-specific setup (e.g. pools, log writer).
- */
-// FIXME
-// private transient postgresql.Driver _driver;
-private transient org.postgresql.Driver _driver;
-//---------
+ /**
+ * Each datasource maintains it's own driver, in case of
+ * driver-specific setup (e.g. pools, log writer).
+ */
+ // FIXME
+ // private transient postgresql.Driver _driver;
+ private transient org.postgresql.Driver _driver;
+ //---------
- public PostgresqlDataSource()
- {
- _logWriter = DriverManager.getLogWriter();
- _loginTimeout = DriverManager.getLoginTimeout();
- }
+ public PostgresqlDataSource()
+ {
+ _logWriter = DriverManager.getLogWriter();
+ _loginTimeout = DriverManager.getLoginTimeout();
+ }
-
- public Connection getConnection()
- throws SQLException
- {
- // Uses the username and password specified for the datasource.
- return getConnection( _user, _password );
- }
+ public Connection getConnection()
+ throws SQLException
+ {
+ // Uses the username and password specified for the datasource.
+ return getConnection( _user, _password );
+ }
- public synchronized Connection getConnection( String user, String password )
- throws SQLException
- {
- Connection conn;
- Properties info;
- String url;
- if ( _driver == null ) {
- try {
- // Constructs a driver for use just by this data source
- // which will produce TwoPhaseConnection-s. This driver
- // is not registered with the driver manager.
-// FIXME
-// _driver = new postgresql.Driver();
-_driver = new org.postgresql.Driver();
-//-----------
-
-//FIXME
-// _driver.setLogWriter( _logWriter );
-// Method seems to be unavailable. Just commented it out.
-//----------
- } catch ( SQLException except ) {
- if ( _logWriter != null )
- _logWriter.println( "DataSource: Failed to initialize JDBC driver: " + except );
- throw except;
- }
+ public synchronized Connection getConnection( String user, String password )
+ throws SQLException
+ {
+ Connection conn;
+ Properties info;
+ String url;
+
+ if ( _driver == null )
+ {
+ try
+ {
+ // Constructs a driver for use just by this data source
+ // which will produce TwoPhaseConnection-s. This driver
+ // is not registered with the driver manager.
+ // FIXME
+ // _driver = new postgresql.Driver();
+ _driver = new org.postgresql.Driver();
+ //-----------
+
+ //FIXME
+ // _driver.setLogWriter( _logWriter );
+ // Method seems to be unavailable. Just commented it out.
+ //----------
+ }
+ catch ( SQLException except )
+ {
+ if ( _logWriter != null )
+ _logWriter.println( "DataSource: Failed to initialize JDBC driver: " + except );
+ throw except;
+ }
+ }
+
+ // Use info to supply properties that are not in the URL.
+ info = new Properties();
+ info.put( "loginTimeout", Integer.toString( _loginTimeout ) );
+
+ // DriverManager will do that and not rely on the URL alone.
+ if ( user == null )
+ {
+ user = _user;
+ password = _password;
+ }
+ if ( user == null || password == null )
+ throw new PSQLException( "postgresql.ds.userpswd" );
+ info.put( "user", user );
+ info.put( "password", password );
+
+ if ( _serverName != null )
+ info.put( "PGHOST", _serverName );
+ if ( _portNumber != DEFAULT_PORT )
+ info.put( "PGPORT", Integer.toString( _portNumber ) );
+ if ( _databaseName != null )
+ info.put( "PGDBNAME", _databaseName );
+
+ // Construct the URL suitable for this driver.
+ url = "jdbc:postgresql:";
+
+ // Attempt to establish a connection. Report a successful
+ // attempt or a failure.
+ try
+ {
+ conn = _driver.connect( url, info );
+ // FIXME
+ // if ( ! ( conn instanceof postgresql.jdbc2.Connection ) ) {
+ if ( ! ( conn instanceof org.postgresql.jdbc2.Connection ) )
+ {
+ //--------
+ if ( _logWriter != null )
+ _logWriter.println( "DataSource: JDBC 1 connections not supported" );
+ throw new PSQLException( "postgresql.ds.onlyjdbc2" );
+ }
+ }
+ catch ( SQLException except )
+ {
+ if ( _logWriter != null )
+ _logWriter.println( "DataSource: getConnection failed " + except );
+ throw except;
+ }
+ if ( conn != null && _logWriter != null )
+ _logWriter.println( "DataSource: getConnection returning " + conn );
+ return conn;
}
- // Use info to supply properties that are not in the URL.
- info = new Properties();
- info.put( "loginTimeout", Integer.toString( _loginTimeout ) );
- // DriverManager will do that and not rely on the URL alone.
- if ( user == null ) {
- user = _user;
- password = _password;
+ public PrintWriter getLogWriter()
+ {
+ return _logWriter;
}
- if ( user == null || password == null )
- throw new PSQLException( "postgresql.ds.userpswd" );
- info.put( "user", user );
- info.put( "password", password );
-
- if ( _serverName != null )
- info.put( "PGHOST", _serverName );
- if ( _portNumber != DEFAULT_PORT )
- info.put( "PGPORT", Integer.toString( _portNumber ) );
- if ( _databaseName != null )
- info.put( "PGDBNAME", _databaseName );
-
- // Construct the URL suitable for this driver.
- url = "jdbc:postgresql:";
-
- // Attempt to establish a connection. Report a successful
- // attempt or a failure.
- try {
- conn = _driver.connect( url, info );
-// FIXME
-// if ( ! ( conn instanceof postgresql.jdbc2.Connection ) ) {
-if ( ! ( conn instanceof org.postgresql.jdbc2.Connection ) ) {
-//--------
- if ( _logWriter != null )
- _logWriter.println( "DataSource: JDBC 1 connections not supported" );
- throw new PSQLException( "postgresql.ds.onlyjdbc2" );
- }
- } catch ( SQLException except ) {
- if ( _logWriter != null )
- _logWriter.println( "DataSource: getConnection failed " + except );
- throw except;
+
+
+ public synchronized void setLogWriter( PrintWriter writer )
+ {
+ // Once a log writer has been set, we cannot set it since some
+ // thread might be conditionally accessing it right now without
+ // synchronizing.
+ if ( writer != null )
+ {
+ if ( _driver != null )
+ // FIXME
+ // _driver.setLogWriter( writer );
+ // Method seems to be unavailable. Commented it out.
+ //----------
+ _logWriter = writer;
+ }
}
- if ( conn != null && _logWriter != null )
- _logWriter.println( "DataSource: getConnection returning " + conn );
- return conn;
- }
- public PrintWriter getLogWriter()
- {
- return _logWriter;
- }
+ public void setLoginTimeout( int seconds )
+ {
+ _loginTimeout = seconds;
+ }
- public synchronized void setLogWriter( PrintWriter writer )
- {
- // Once a log writer has been set, we cannot set it since some
- // thread might be conditionally accessing it right now without
- // synchronizing.
- if ( writer != null ) {
- if ( _driver != null )
-// FIXME
-// _driver.setLogWriter( writer );
-// Method seems to be unavailable. Commented it out.
-//----------
- _logWriter = writer;
+ public synchronized int getLoginTimeout()
+ {
+ return _loginTimeout;
}
- }
-
-
- public void setLoginTimeout( int seconds )
- {
- _loginTimeout = seconds;
- }
-
-
- public synchronized int getLoginTimeout()
- {
- return _loginTimeout;
- }
-
-
- /**
- * Sets the name of the particular database on the server.
- * The standard name for this property is <tt>databaseName</tt>.
- *
- * @param databaseName The name of the particular database on the server
- */
- public synchronized void setDatabaseName( String databaseName )
- {
- if ( databaseName == null )
- throw new NullPointerException( "DataSource: Argument 'databaseName' is null" );
- _databaseName = databaseName;
- }
-
-
- /**
- * Returns the name of the particular database on the server.
- * The standard name for this property is <tt>databaseName</tt>.
- *
- * @return The name of the particular database on the server
- */
- public String getDatabaseName()
- {
- return _databaseName;
- }
-
-
- /**
- * Sets the description of this datasource.
- * The standard name for this property is <tt>description</tt>.
- *
- * @param description The description of this datasource
- */
- public synchronized void setDescription( String description )
- {
- if ( description == null )
- throw new NullPointerException( "DataSource: Argument 'description' is null" );
- _description = description;
- }
-
-
- /**
- * Returns the description of this datasource.
- * The standard name for this property is <tt>description</tt>.
- *
- * @return The description of this datasource
- */
- public String getDescription()
- {
- return _description;
- }
-
-
- /**
- * Sets the database password.
- * The standard name for this property is <tt>password</tt>.
- *
- * @param password The database password
- */
- public synchronized void setPassword( String password )
- {
- _password = password;
- }
-
-
- /**
- * Returns the database password.
- * The standard name for this property is <tt>password</tt>.
- *
- * @return The database password
- */
- public String getPassword()
- {
- return _password;
- }
-
-
- /**
- * Sets the port number where a server is listening.
- * The standard name for this property is <tt>portNumber</tt>.
- *
- * @param portNumber The port number where a server is listening
- */
- public synchronized void setPortNumber( int portNumber )
- {
- _portNumber = portNumber;
- }
-
-
- /**
- * Returns the port number where a server is listening.
- * The standard name for this property is <tt>portNumber</tt>.
- *
- * @return The port number where a server is listening
- */
- public int getPortNumber()
- {
- return _portNumber;
- }
-
-
- /**
- * Sets the database server name.
-
- * The standard name for this property is <tt>serverName</tt>.
- *
- * @param serverName The database server name
- */
- public synchronized void setServerName( String serverName )
- {
- _serverName = serverName;
- }
-
-
- /**
- * Returns the database server name.
- * The standard name for this property is <tt>serverName</tt>.
- *
- * @return The database server name
- */
- public String getServerName()
- {
- return _serverName;
- }
-
-
- /**
- * Sets the user's account name.
- * The standard name for this property is <tt>user</tt>.
- *
- * @param user The user's account name
- */
- public synchronized void setUser( String user )
- {
- _user = user;
- }
-
-
- /**
- * Returns the user's account name.
- * The standard name for this property is <tt>user</tt>.
- *
- * @return The user's account name
- */
- public String getUser()
- {
- return _user;
- }
-
-
- /**
- * Returns true if this datasource and the other are equal.
- * The two datasources are equal if and only if they will produce
- * the exact same connections. Connection properties like database
- * name, user name, etc are comapred. Setup properties like
- * description, log writer, etc are not compared.
- */
- public synchronized boolean equals( Object other )
- {
- if ( other == this )
- return true;
- if ( other == null || ! ( other instanceof PostgresqlDataSource ) )
- return false;
-
- PostgresqlDataSource with;
-
- with = (PostgresqlDataSource) other;
- if ( _databaseName != null && _databaseName.equals( with._databaseName ) )
- if ( _portNumber == with._portNumber &&
- ( ( _serverName == null && with._serverName == null ) ||
- ( _serverName != null && _serverName.equals( with._serverName ) ) ) )
- if ( ( _user == null && with._user == null ) ||
- ( _user != null && _password != null && _user.equals( with._user ) &&
- _password.equals( with._password ) ) )
- return true;
- return false;
- }
-
-
- public String toString()
- {
- if ( _description != null )
- return _description;
- else {
- String url;
-
- url = "jdbc:postgresql:";
- if ( _serverName != null ) {
- if ( _portNumber == DEFAULT_PORT )
- url = url + "//" + _serverName + "/";
- else
- url = url + "//" + _serverName + ":" + _portNumber + "/";
- } else if ( _portNumber != DEFAULT_PORT )
- url = url + "//localhost:" + _portNumber + "/";
- if ( _databaseName != null )
- url = url + _databaseName;
- return "DataSource " + url;
+
+
+ /**
+ * Sets the name of the particular database on the server.
+ * The standard name for this property is <tt>databaseName</tt>.
+ *
+ * @param databaseName The name of the particular database on the server
+ */
+ public synchronized void setDatabaseName( String databaseName )
+ {
+ if ( databaseName == null )
+ throw new NullPointerException( "DataSource: Argument 'databaseName' is null" );
+ _databaseName = databaseName;
+ }
+
+
+ /**
+ * Returns the name of the particular database on the server.
+ * The standard name for this property is <tt>databaseName</tt>.
+ *
+ * @return The name of the particular database on the server
+ */
+ public String getDatabaseName()
+ {
+ return _databaseName;
+ }
+
+
+ /**
+ * Sets the description of this datasource.
+ * The standard name for this property is <tt>description</tt>.
+ *
+ * @param description The description of this datasource
+ */
+ public synchronized void setDescription( String description )
+ {
+ if ( description == null )
+ throw new NullPointerException( "DataSource: Argument 'description' is null" );
+ _description = description;
+ }
+
+
+ /**
+ * Returns the description of this datasource.
+ * The standard name for this property is <tt>description</tt>.
+ *
+ * @return The description of this datasource
+ */
+ public String getDescription()
+ {
+ return _description;
+ }
+
+
+ /**
+ * Sets the database password.
+ * The standard name for this property is <tt>password</tt>.
+ *
+ * @param password The database password
+ */
+ public synchronized void setPassword( String password )
+ {
+ _password = password;
+ }
+
+
+ /**
+ * Returns the database password.
+ * The standard name for this property is <tt>password</tt>.
+ *
+ * @return The database password
+ */
+ public String getPassword()
+ {
+ return _password;
+ }
+
+
+ /**
+ * Sets the port number where a server is listening.
+ * The standard name for this property is <tt>portNumber</tt>.
+ *
+ * @param portNumber The port number where a server is listening
+ */
+ public synchronized void setPortNumber( int portNumber )
+ {
+ _portNumber = portNumber;
+ }
+
+
+ /**
+ * Returns the port number where a server is listening.
+ * The standard name for this property is <tt>portNumber</tt>.
+ *
+ * @return The port number where a server is listening
+ */
+ public int getPortNumber()
+ {
+ return _portNumber;
+ }
+
+
+ /**
+ * Sets the database server name.
+
+ * The standard name for this property is <tt>serverName</tt>.
+ *
+ * @param serverName The database server name
+ */
+ public synchronized void setServerName( String serverName )
+ {
+ _serverName = serverName;
+ }
+
+
+ /**
+ * Returns the database server name.
+ * The standard name for this property is <tt>serverName</tt>.
+ *
+ * @return The database server name
+ */
+ public String getServerName()
+ {
+ return _serverName;
+ }
+
+
+ /**
+ * Sets the user's account name.
+ * The standard name for this property is <tt>user</tt>.
+ *
+ * @param user The user's account name
+ */
+ public synchronized void setUser( String user )
+ {
+ _user = user;
+ }
+
+
+ /**
+ * Returns the user's account name.
+ * The standard name for this property is <tt>user</tt>.
+ *
+ * @return The user's account name
+ */
+ public String getUser()
+ {
+ return _user;
+ }
+
+
+ /**
+ * Returns true if this datasource and the other are equal.
+ * The two datasources are equal if and only if they will produce
+ * the exact same connections. Connection properties like database
+ * name, user name, etc are comapred. Setup properties like
+ * description, log writer, etc are not compared.
+ */
+ public synchronized boolean equals( Object other )
+ {
+ if ( other == this )
+ return true;
+ if ( other == null || ! ( other instanceof PostgresqlDataSource ) )
+ return false;
+
+ PostgresqlDataSource with;
+
+ with = (PostgresqlDataSource) other;
+ if ( _databaseName != null && _databaseName.equals( with._databaseName ) )
+ if ( _portNumber == with._portNumber &&
+ ( ( _serverName == null && with._serverName == null ) ||
+ ( _serverName != null && _serverName.equals( with._serverName ) ) ) )
+ if ( ( _user == null && with._user == null ) ||
+ ( _user != null && _password != null && _user.equals( with._user ) &&
+ _password.equals( with._password ) ) )
+ return true;
+ return false;
}
- }
-
-
- public synchronized Reference getReference()
- {
- Reference ref;
-
- // We use same object as factory.
- ref = new Reference( getClass().getName(), getClass().getName(), null );
- // Mandatory properties
- ref.add( new StringRefAddr( "description", _description ) );
- ref.add( new StringRefAddr( "databaseName", _databaseName ) );
- ref.add( new StringRefAddr( "loginTimeout", Integer.toString( _loginTimeout ) ) );
- // Optional properties
- if ( _user != null )
- ref.add( new StringRefAddr( "user", _user ) );
- if ( _password != null )
- ref.add( new StringRefAddr( "password", _password ) );
- if ( _serverName != null )
- ref.add( new StringRefAddr( "serverName", _serverName ) );
- if ( _portNumber != DEFAULT_PORT )
- ref.add( new StringRefAddr( "portNumber", Integer.toString( _portNumber ) ) );
- ref.add( new StringRefAddr( "transactionTimeout", Integer.toString( getTransactionTimeout() ) ) );
- return ref;
- }
-
-
- public Object getObjectInstance( Object refObj, Name name, Context nameCtx, Hashtable env )
- throws NamingException
- {
- Reference ref;
-
- // Can only reconstruct from a reference.
- if ( refObj instanceof Reference ) {
- ref = (Reference) refObj;
- // Make sure reference is of datasource class.
- if ( ref.getClassName().equals( getClass().getName() ) ) {
-
- PostgresqlDataSource ds;
- RefAddr addr;
-
- try {
- ds = (PostgresqlDataSource) Class.forName( ref.getClassName() ).newInstance();
- } catch ( Exception except ) {
- throw new NamingException( except.toString() );
+
+
+ public String toString()
+ {
+ if ( _description != null )
+ return _description;
+ else
+ {
+ String url;
+
+ url = "jdbc:postgresql:";
+ if ( _serverName != null )
+ {
+ if ( _portNumber == DEFAULT_PORT )
+ url = url + "//" + _serverName + "/";
+ else
+ url = url + "//" + _serverName + ":" + _portNumber + "/";
+ }
+ else if ( _portNumber != DEFAULT_PORT )
+ url = url + "//localhost:" + _portNumber + "/";
+ if ( _databaseName != null )
+ url = url + _databaseName;
+ return "DataSource " + url;
}
+ }
+
+
+ public synchronized Reference getReference()
+ {
+ Reference ref;
+
+ // We use same object as factory.
+ ref = new Reference( getClass().getName(), getClass().getName(), null );
// Mandatory properties
- ds._description = (String) ref.get( "description" ).getContent();
- ds._databaseName = (String) ref.get( "databaseName" ).getContent();
- ds._loginTimeout = Integer.parseInt( (String) ref.get( "loginTimeout" ).getContent() );
+ ref.add( new StringRefAddr( "description", _description ) );
+ ref.add( new StringRefAddr( "databaseName", _databaseName ) );
+ ref.add( new StringRefAddr( "loginTimeout", Integer.toString( _loginTimeout ) ) );
// Optional properties
- addr = ref.get( "user" );
- if ( addr != null )
- ds._user = (String) addr.getContent();
- addr = ref.get( "password" );
- if ( addr != null )
- ds._password = (String) addr.getContent();
- addr = ref.get( "serverName" );
- if ( addr != null )
- ds._serverName = (String) addr.getContent();
- addr = ref.get( "portNumber" );
- if ( addr != null )
- ds._portNumber = Integer.parseInt( (String) addr.getContent() );
- addr = ref.get( "transactionTimeout" );
- if ( addr != null )
- setTransactionTimeout( Integer.parseInt( (String) addr.getContent() ) );
- return ds;
-
- } else
- throw new NamingException( "DataSource: Reference not constructed from class " + getClass().getName() );
- } else if ( refObj instanceof Remote )
- return refObj;
- else
- return null;
- }
+ if ( _user != null )
+ ref.add( new StringRefAddr( "user", _user ) );
+ if ( _password != null )
+ ref.add( new StringRefAddr( "password", _password ) );
+ if ( _serverName != null )
+ ref.add( new StringRefAddr( "serverName", _serverName ) );
+ if ( _portNumber != DEFAULT_PORT )
+ ref.add( new StringRefAddr( "portNumber", Integer.toString( _portNumber ) ) );
+ ref.add( new StringRefAddr( "transactionTimeout", Integer.toString( getTransactionTimeout() ) ) );
+ return ref;
+ }
+
+
+ public Object getObjectInstance( Object refObj, Name name, Context nameCtx, Hashtable env )
+ throws NamingException
+ {
+ Reference ref;
+
+ // Can only reconstruct from a reference.
+ if ( refObj instanceof Reference )
+ {
+ ref = (Reference) refObj;
+ // Make sure reference is of datasource class.
+ if ( ref.getClassName().equals( getClass().getName() ) )
+ {
+
+ PostgresqlDataSource ds;
+ RefAddr addr;
+
+ try
+ {
+ ds = (PostgresqlDataSource) Class.forName( ref.getClassName() ).newInstance();
+ }
+ catch ( Exception except )
+ {
+ throw new NamingException( except.toString() );
+ }
+ // Mandatory properties
+ ds._description = (String) ref.get( "description" ).getContent();
+ ds._databaseName = (String) ref.get( "databaseName" ).getContent();
+ ds._loginTimeout = Integer.parseInt( (String) ref.get( "loginTimeout" ).getContent() );
+ // Optional properties
+ addr = ref.get( "user" );
+ if ( addr != null )
+ ds._user = (String) addr.getContent();
+ addr = ref.get( "password" );
+ if ( addr != null )
+ ds._password = (String) addr.getContent();
+ addr = ref.get( "serverName" );
+ if ( addr != null )
+ ds._serverName = (String) addr.getContent();
+ addr = ref.get( "portNumber" );
+ if ( addr != null )
+ ds._portNumber = Integer.parseInt( (String) addr.getContent() );
+ addr = ref.get( "transactionTimeout" );
+ if ( addr != null )
+ setTransactionTimeout( Integer.parseInt( (String) addr.getContent() ) );
+ return ds;
+
+ }
+ else
+ throw new NamingException( "DataSource: Reference not constructed from class " + getClass().getName() );
+ }
+ else if ( refObj instanceof Remote )
+ return refObj;
+ else
+ return null;
+ }
}
diff --git a/src/interfaces/jdbc/org/postgresql/ResultSet.java b/src/interfaces/jdbc/org/postgresql/ResultSet.java
index 3274b1eb38c..9febb88613d 100644
--- a/src/interfaces/jdbc/org/postgresql/ResultSet.java
+++ b/src/interfaces/jdbc/org/postgresql/ResultSet.java
@@ -15,198 +15,201 @@ import org.postgresql.util.*;
*/
public abstract class ResultSet
{
- protected Vector rows; // The results
- protected Field fields[]; // The field descriptions
- protected String status; // Status of the result
- protected boolean binaryCursor = false; // is the data binary or Strings
- protected int updateCount; // How many rows did we get back?
- protected int insertOID; // The oid of an inserted row
- protected int current_row; // Our pointer to where we are at
- protected byte[][] this_row; // the current row result
- protected Connection connection; // the connection which we returned from
- protected SQLWarning warnings = null; // The warning chain
- protected boolean wasNullFlag = false; // the flag for wasNull()
-
- // We can chain multiple resultSets together - this points to
- // next resultSet in the chain.
- protected ResultSet next = null;
-
- /**
- * Create a new ResultSet - Note that we create ResultSets to
- * represent the results of everything.
- *
- * @param fields an array of Field objects (basically, the
- * ResultSet MetaData)
- * @param tuples Vector of the actual data
- * @param status the status string returned from the back end
- * @param updateCount the number of rows affected by the operation
- * @param cursor the positioned update/delete cursor name
- */
- public ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount,int insertOID, boolean binaryCursor)
- {
- this.connection = conn;
- this.fields = fields;
- this.rows = tuples;
- this.status = status;
- this.updateCount = updateCount;
- this.insertOID = insertOID;
- this.this_row = null;
- this.current_row = -1;
- this.binaryCursor = binaryCursor;
- }
-
-
- /**
- * Create a new ResultSet - Note that we create ResultSets to
- * represent the results of everything.
- *
- * @param fields an array of Field objects (basically, the
- * ResultSet MetaData)
- * @param tuples Vector of the actual data
- * @param status the status string returned from the back end
- * @param updateCount the number of rows affected by the operation
- * @param cursor the positioned update/delete cursor name
- */
- public ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount)
- {
- this(conn,fields,tuples,status,updateCount,0,false);
- }
-
- /**
- * We at times need to know if the resultSet we are working
- * with is the result of an UPDATE, DELETE or INSERT (in which
- * case, we only have a row count), or of a SELECT operation
- * (in which case, we have multiple fields) - this routine
- * tells us.
- *
- * @return true if we have tuples available
- */
- public boolean reallyResultSet()
- {
- return (fields != null);
- }
-
- /**
- * Since ResultSets can be chained, we need some method of
- * finding the next one in the chain. The method getNext()
- * returns the next one in the chain.
- *
- * @return the next ResultSet, or null if there are none
- */
- public java.sql.ResultSet getNext()
- {
- return (java.sql.ResultSet)next;
- }
-
- /**
- * This following method allows us to add a ResultSet object
- * to the end of the current chain.
- *
- * @param r the resultset to add to the end of the chain.
- */
- public void append(ResultSet r)
- {
- if (next == null)
- next = r;
- else
- next.append(r);
- }
-
- /**
- * If we are just a place holder for results, we still need
- * to get an updateCount. This method returns it.
- *
- * @return the updateCount
- */
- public int getResultCount()
- {
- return updateCount;
- }
-
- /**
- * We also need to provide a couple of auxiliary functions for
- * the implementation of the ResultMetaData functions. In
- * particular, we need to know the number of rows and the
- * number of columns. Rows are also known as Tuples
- *
- * @return the number of rows
- */
- public int getTupleCount()
- {
- return rows.size();
- }
-
- /**
- * getColumnCount returns the number of columns
- *
- * @return the number of columns
- */
- public int getColumnCount()
- {
- return fields.length;
- }
-
- /**
- * Returns the status message from the backend.<p>
- * It is used internally by the driver.
- *
- * @return the status string from the backend
- */
- public String getStatusString()
- {
- return status;
- }
-
- /**
- * returns the OID of a field.<p>
- * It is used internally by the driver.
- *
- * @param field field id
- * @return the oid of that field's type
- */
- public int getColumnOID(int field)
- {
- return fields[field-1].getOID();
- }
-
- /**
- * returns the OID of the last inserted row
- */
- public int getInsertedOID()
- {
- return insertOID;
- }
-
- /**
- * This is part of the JDBC API, but is required by org.postgresql.Field
- */
- public abstract void close() throws SQLException;
- public abstract boolean next() throws SQLException;
- public abstract String getString(int i) throws SQLException;
-
- /**
- * This is used to fix get*() methods on Money fields. It should only be
- * used by those methods!
- *
- * It converts ($##.##) to -##.## and $##.## to ##.##
- */
- public String getFixedString(int col) throws SQLException {
- String s = getString(col);
-
- // Handle SQL Null
- wasNullFlag = (this_row[col - 1] == null);
- if(wasNullFlag)
- return null;
-
- // Handle Money
- if(s.charAt(0)=='(') {
- s="-"+org.postgresql.util.PGtokenizer.removePara(s).substring(1);
- }
- if(s.charAt(0)=='$') {
- s=s.substring(1);
- }
-
- return s;
- }
+ protected Vector rows; // The results
+ protected Field fields[]; // The field descriptions
+ protected String status; // Status of the result
+ protected boolean binaryCursor = false; // is the data binary or Strings
+ protected int updateCount; // How many rows did we get back?
+ protected int insertOID; // The oid of an inserted row
+ protected int current_row; // Our pointer to where we are at
+ protected byte[][] this_row; // the current row result
+ protected Connection connection; // the connection which we returned from
+ protected SQLWarning warnings = null; // The warning chain
+ protected boolean wasNullFlag = false; // the flag for wasNull()
+
+ // We can chain multiple resultSets together - this points to
+ // next resultSet in the chain.
+ protected ResultSet next = null;
+
+ /**
+ * Create a new ResultSet - Note that we create ResultSets to
+ * represent the results of everything.
+ *
+ * @param fields an array of Field objects (basically, the
+ * ResultSet MetaData)
+ * @param tuples Vector of the actual data
+ * @param status the status string returned from the back end
+ * @param updateCount the number of rows affected by the operation
+ * @param cursor the positioned update/delete cursor name
+ */
+ public ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount, int insertOID, boolean binaryCursor)
+ {
+ this.connection = conn;
+ this.fields = fields;
+ this.rows = tuples;
+ this.status = status;
+ this.updateCount = updateCount;
+ this.insertOID = insertOID;
+ this.this_row = null;
+ this.current_row = -1;
+ this.binaryCursor = binaryCursor;
+ }
+
+
+ /**
+ * Create a new ResultSet - Note that we create ResultSets to
+ * represent the results of everything.
+ *
+ * @param fields an array of Field objects (basically, the
+ * ResultSet MetaData)
+ * @param tuples Vector of the actual data
+ * @param status the status string returned from the back end
+ * @param updateCount the number of rows affected by the operation
+ * @param cursor the positioned update/delete cursor name
+ */
+ public ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount)
+ {
+ this(conn, fields, tuples, status, updateCount, 0, false);
+ }
+
+ /**
+ * We at times need to know if the resultSet we are working
+ * with is the result of an UPDATE, DELETE or INSERT (in which
+ * case, we only have a row count), or of a SELECT operation
+ * (in which case, we have multiple fields) - this routine
+ * tells us.
+ *
+ * @return true if we have tuples available
+ */
+ public boolean reallyResultSet()
+ {
+ return (fields != null);
+ }
+
+ /**
+ * Since ResultSets can be chained, we need some method of
+ * finding the next one in the chain. The method getNext()
+ * returns the next one in the chain.
+ *
+ * @return the next ResultSet, or null if there are none
+ */
+ public java.sql.ResultSet getNext()
+ {
+ return (java.sql.ResultSet)next;
+ }
+
+ /**
+ * This following method allows us to add a ResultSet object
+ * to the end of the current chain.
+ *
+ * @param r the resultset to add to the end of the chain.
+ */
+ public void append(ResultSet r)
+ {
+ if (next == null)
+ next = r;
+ else
+ next.append(r);
+ }
+
+ /**
+ * If we are just a place holder for results, we still need
+ * to get an updateCount. This method returns it.
+ *
+ * @return the updateCount
+ */
+ public int getResultCount()
+ {
+ return updateCount;
+ }
+
+ /**
+ * We also need to provide a couple of auxiliary functions for
+ * the implementation of the ResultMetaData functions. In
+ * particular, we need to know the number of rows and the
+ * number of columns. Rows are also known as Tuples
+ *
+ * @return the number of rows
+ */
+ public int getTupleCount()
+ {
+ return rows.size();
+ }
+
+ /**
+ * getColumnCount returns the number of columns
+ *
+ * @return the number of columns
+ */
+ public int getColumnCount()
+ {
+ return fields.length;
+ }
+
+ /**
+ * Returns the status message from the backend.<p>
+ * It is used internally by the driver.
+ *
+ * @return the status string from the backend
+ */
+ public String getStatusString()
+ {
+ return status;
+ }
+
+ /**
+ * returns the OID of a field.<p>
+ * It is used internally by the driver.
+ *
+ * @param field field id
+ * @return the oid of that field's type
+ */
+ public int getColumnOID(int field)
+ {
+ return fields[field -1].getOID();
+ }
+
+ /**
+ * returns the OID of the last inserted row
+ */
+ public int getInsertedOID()
+ {
+ return insertOID;
+ }
+
+ /**
+ * This is part of the JDBC API, but is required by org.postgresql.Field
+ */
+ public abstract void close() throws SQLException;
+ public abstract boolean next() throws SQLException;
+ public abstract String getString(int i) throws SQLException;
+
+ /**
+ * This is used to fix get*() methods on Money fields. It should only be
+ * used by those methods!
+ *
+ * It converts ($##.##) to -##.## and $##.## to ##.##
+ */
+ public String getFixedString(int col) throws SQLException
+ {
+ String s = getString(col);
+
+ // Handle SQL Null
+ wasNullFlag = (this_row[col - 1] == null);
+ if (wasNullFlag)
+ return null;
+
+ // Handle Money
+ if (s.charAt(0) == '(')
+ {
+ s = "-" + org.postgresql.util.PGtokenizer.removePara(s).substring(1);
+ }
+ if (s.charAt(0) == '$')
+ {
+ s = s.substring(1);
+ }
+
+ return s;
+ }
}
diff --git a/src/interfaces/jdbc/org/postgresql/Statement.java b/src/interfaces/jdbc/org/postgresql/Statement.java
index 6acdd8bfa58..2b201c8af40 100644
--- a/src/interfaces/jdbc/org/postgresql/Statement.java
+++ b/src/interfaces/jdbc/org/postgresql/Statement.java
@@ -23,284 +23,299 @@ import org.postgresql.util.PSQLException;
* JDBC3.
*/
-public abstract class Statement {
-
- /** The warnings chain. */
- protected SQLWarning warnings = null;
-
- /** The current results */
- protected java.sql.ResultSet result = null;
-
- /** Maximum number of rows to return, 0 = unlimited */
- protected int maxrows = 0;
-
- /** Timeout (in seconds) for a query (not used) */
- protected int timeout = 0;
-
- protected boolean escapeProcessing = true;
-
- // Static variables for parsing SQL when escapeProcessing is true.
- private static final short IN_SQLCODE = 0;
- private static final short IN_STRING = 1;
- private static final short BACKSLASH =2;
- private static final short ESC_TIMEDATE = 3;
-
- public Statement() {
- }
-
- /**
- * Returns the status message from the current Result.<p>
- * This is used internally by the driver.
- *
- * @return status message from backend
- */
- public String getResultStatusString() {
- if (result == null)
- return null;
- return ((org.postgresql.ResultSet) result).getStatusString();
- }
-
- /**
- * The maxRows limit is set to limit the number of rows that
- * any ResultSet can contain. If the limit is exceeded, the
- * excess rows are silently dropped.
- *
- * @return the current maximum row limit; zero means unlimited
- * @exception SQLException if a database access error occurs
- */
- public int getMaxRows() throws SQLException {
- return maxrows;
- }
-
- /**
- * Set the maximum number of rows
- *
- * @param max the new max rows limit; zero means unlimited
- * @exception SQLException if a database access error occurs
- * @see getMaxRows
- */
- public void setMaxRows(int max) throws SQLException {
- maxrows = max;
- }
-
- /**
- * If escape scanning is on (the default), the driver will do escape
- * substitution before sending the SQL to the database.
- *
- * @param enable true to enable; false to disable
- * @exception SQLException if a database access error occurs
- */
- public void setEscapeProcessing(boolean enable) throws SQLException {
- escapeProcessing = enable;
- }
-
- /**
- * The queryTimeout limit is the number of seconds the driver
- * will wait for a Statement to execute. If the limit is
- * exceeded, a SQLException is thrown.
- *
- * @return the current query timeout limit in seconds; 0 = unlimited
- * @exception SQLException if a database access error occurs
- */
- public int getQueryTimeout() throws SQLException {
- return timeout;
- }
-
- /**
- * Sets the queryTimeout limit
- *
- * @param seconds - the new query timeout limit in seconds
- * @exception SQLException if a database access error occurs
- */
- public void setQueryTimeout(int seconds) throws SQLException {
- timeout = seconds;
- }
-
- /**
- * The first warning reported by calls on this Statement is
- * returned. A Statement's execute methods clear its SQLWarning
- * chain. Subsequent Statement warnings will be chained to this
- * SQLWarning.
- *
- * <p>The Warning chain is automatically cleared each time a statement
- * is (re)executed.
- *
- * <p><B>Note:</B> If you are processing a ResultSet then any warnings
- * associated with ResultSet reads will be chained on the ResultSet
- * object.
- *
- * @return the first SQLWarning on null
- * @exception SQLException if a database access error occurs
- */
- public SQLWarning getWarnings() throws SQLException {
- return warnings;
- }
-
- /**
- * The maxFieldSize limit (in bytes) is the maximum amount of
- * data returned for any column value; it only applies to
- * BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR and LONGVARCHAR
- * columns. If the limit is exceeded, the excess data is silently
- * discarded.
- *
- * @return the current max column size limit; zero means unlimited
- * @exception SQLException if a database access error occurs
- */
- public int getMaxFieldSize() throws SQLException {
- return 8192; // We cannot change this
- }
-
- /**
- * Sets the maxFieldSize - NOT! - We throw an SQLException just
- * to inform them to stop doing this.
- *
- * @param max the new max column size limit; zero means unlimited
- * @exception SQLException if a database access error occurs
- */
- public void setMaxFieldSize(int max) throws SQLException {
- throw new PSQLException("postgresql.stat.maxfieldsize");
- }
-
- /**
- * After this call, getWarnings returns null until a new warning
- * is reported for this Statement.
- *
- * @exception SQLException if a database access error occurs
- */
- public void clearWarnings() throws SQLException {
- warnings = null;
- }
-
- /**
- * Cancel can be used by one thread to cancel a statement that
- * is being executed by another thread.
- * <p>
- * Not implemented, this method is a no-op.
- *
- * @exception SQLException only because thats the spec.
- */
- public void cancel() throws SQLException {
- // FIXME: Cancel feature has been available since 6.4. Implement it here!
- }
-
- /**
- * New in 7.1: Returns the Last inserted oid. This should be used, rather
- * than the old method using getResultSet, which for executeUpdate returns
- * null.
- * @return OID of last insert
- */
- public int getInsertedOID() throws SQLException {
- if (result == null)
- return 0;
- return ((org.postgresql.ResultSet) result).getInsertedOID();
- }
-
- /**
- * getResultSet returns the current result as a ResultSet. It
- * should only be called once per result.
- *
- * @return the current result set; null if there are no more
- * @exception SQLException if a database access error occurs (why?)
- */
- public java.sql.ResultSet getResultSet() throws SQLException {
- if (result != null && ((org.postgresql.ResultSet) result).reallyResultSet())
- return result;
- return null;
- }
-
- /**
- * In many cases, it is desirable to immediately release a
- * Statement's database and JDBC resources instead of waiting
- * for this to happen when it is automatically closed. The
- * close method provides this immediate release.
- *
- * <p><B>Note:</B> A Statement is automatically closed when it is
- * garbage collected. When a Statement is closed, its current
- * ResultSet, if one exists, is also closed.
- *
- * @exception SQLException if a database access error occurs (why?)
- */
- public void close() throws SQLException {
- // Force the ResultSet to close
- java.sql.ResultSet rs = getResultSet();
- if(rs!=null)
- rs.close();
-
- // Disasociate it from us (For Garbage Collection)
- result = null;
- }
-
- /**
- * Filter the SQL string of Java SQL Escape clauses.
- *
- * Currently implemented Escape clauses are those mentioned in 11.3
- * in the specification. Basically we look through the sql string for
- * {d xxx}, {t xxx} or {ts xxx} in non-string sql code. When we find
- * them, we just strip the escape part leaving only the xxx part.
- * So, something like "select * from x where d={d '2001-10-09'}" would
- * return "select * from x where d= '2001-10-09'".
- */
- protected static String escapeSQL(String sql)
- {
- // Since escape codes can only appear in SQL CODE, we keep track
- // of if we enter a string or not.
- StringBuffer newsql = new StringBuffer();
- short state = IN_SQLCODE;
-
- int i = -1;
- int len = sql.length();
- while(++i < len)
- {
- char c = sql.charAt(i);
- switch(state)
- {
- case IN_SQLCODE:
- if(c == '\'') // start of a string?
- state = IN_STRING;
- else if(c == '{') // start of an escape code?
- if(i+1 < len)
- {
- char next = sql.charAt(i+1);
- if(next == 'd')
- {
- state = ESC_TIMEDATE;
- i++;
- break;
- }
- else if(next == 't')
- {
- state = ESC_TIMEDATE;
- i += (i+2 < len && sql.charAt(i+2) == 's') ? 2 : 1;
- break;
- }
- }
- newsql.append(c);
- break;
-
- case IN_STRING:
- if(c == '\'') // end of string?
- state = IN_SQLCODE;
- else if(c == '\\') // a backslash?
- state = BACKSLASH;
-
- newsql.append(c);
- break;
-
- case BACKSLASH:
- state = IN_STRING;
-
- newsql.append(c);
- break;
-
- case ESC_TIMEDATE:
- if(c == '}')
- state = IN_SQLCODE; // end of escape code.
- else
- newsql.append(c);
- break;
- } // end switch
- }
-
- return newsql.toString();
- }
+public abstract class Statement
+{
+
+ /** The warnings chain. */
+ protected SQLWarning warnings = null;
+
+ /** The current results */
+ protected java.sql.ResultSet result = null;
+
+ /** Maximum number of rows to return, 0 = unlimited */
+ protected int maxrows = 0;
+
+ /** Timeout (in seconds) for a query (not used) */
+ protected int timeout = 0;
+
+ protected boolean escapeProcessing = true;
+
+ // Static variables for parsing SQL when escapeProcessing is true.
+ private static final short IN_SQLCODE = 0;
+ private static final short IN_STRING = 1;
+ private static final short BACKSLASH = 2;
+ private static final short ESC_TIMEDATE = 3;
+
+ public Statement()
+ {}
+
+ /**
+ * Returns the status message from the current Result.<p>
+ * This is used internally by the driver.
+ *
+ * @return status message from backend
+ */
+ public String getResultStatusString()
+ {
+ if (result == null)
+ return null;
+ return ((org.postgresql.ResultSet) result).getStatusString();
+ }
+
+ /**
+ * The maxRows limit is set to limit the number of rows that
+ * any ResultSet can contain. If the limit is exceeded, the
+ * excess rows are silently dropped.
+ *
+ * @return the current maximum row limit; zero means unlimited
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxRows() throws SQLException
+ {
+ return maxrows;
+ }
+
+ /**
+ * Set the maximum number of rows
+ *
+ * @param max the new max rows limit; zero means unlimited
+ * @exception SQLException if a database access error occurs
+ * @see getMaxRows
+ */
+ public void setMaxRows(int max) throws SQLException
+ {
+ maxrows = max;
+ }
+
+ /**
+ * If escape scanning is on (the default), the driver will do escape
+ * substitution before sending the SQL to the database.
+ *
+ * @param enable true to enable; false to disable
+ * @exception SQLException if a database access error occurs
+ */
+ public void setEscapeProcessing(boolean enable) throws SQLException
+ {
+ escapeProcessing = enable;
+ }
+
+ /**
+ * The queryTimeout limit is the number of seconds the driver
+ * will wait for a Statement to execute. If the limit is
+ * exceeded, a SQLException is thrown.
+ *
+ * @return the current query timeout limit in seconds; 0 = unlimited
+ * @exception SQLException if a database access error occurs
+ */
+ public int getQueryTimeout() throws SQLException
+ {
+ return timeout;
+ }
+
+ /**
+ * Sets the queryTimeout limit
+ *
+ * @param seconds - the new query timeout limit in seconds
+ * @exception SQLException if a database access error occurs
+ */
+ public void setQueryTimeout(int seconds) throws SQLException
+ {
+ timeout = seconds;
+ }
+
+ /**
+ * The first warning reported by calls on this Statement is
+ * returned. A Statement's execute methods clear its SQLWarning
+ * chain. Subsequent Statement warnings will be chained to this
+ * SQLWarning.
+ *
+ * <p>The Warning chain is automatically cleared each time a statement
+ * is (re)executed.
+ *
+ * <p><B>Note:</B> If you are processing a ResultSet then any warnings
+ * associated with ResultSet reads will be chained on the ResultSet
+ * object.
+ *
+ * @return the first SQLWarning on null
+ * @exception SQLException if a database access error occurs
+ */
+ public SQLWarning getWarnings() throws SQLException
+ {
+ return warnings;
+ }
+
+ /**
+ * The maxFieldSize limit (in bytes) is the maximum amount of
+ * data returned for any column value; it only applies to
+ * BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR and LONGVARCHAR
+ * columns. If the limit is exceeded, the excess data is silently
+ * discarded.
+ *
+ * @return the current max column size limit; zero means unlimited
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxFieldSize() throws SQLException
+ {
+ return 8192; // We cannot change this
+ }
+
+ /**
+ * Sets the maxFieldSize - NOT! - We throw an SQLException just
+ * to inform them to stop doing this.
+ *
+ * @param max the new max column size limit; zero means unlimited
+ * @exception SQLException if a database access error occurs
+ */
+ public void setMaxFieldSize(int max) throws SQLException
+ {
+ throw new PSQLException("postgresql.stat.maxfieldsize");
+ }
+
+ /**
+ * After this call, getWarnings returns null until a new warning
+ * is reported for this Statement.
+ *
+ * @exception SQLException if a database access error occurs
+ */
+ public void clearWarnings() throws SQLException
+ {
+ warnings = null;
+ }
+
+ /**
+ * Cancel can be used by one thread to cancel a statement that
+ * is being executed by another thread.
+ * <p>
+ * Not implemented, this method is a no-op.
+ *
+ * @exception SQLException only because thats the spec.
+ */
+ public void cancel() throws SQLException
+ {
+ // FIXME: Cancel feature has been available since 6.4. Implement it here!
+ }
+
+ /**
+ * New in 7.1: Returns the Last inserted oid. This should be used, rather
+ * than the old method using getResultSet, which for executeUpdate returns
+ * null.
+ * @return OID of last insert
+ */
+ public int getInsertedOID() throws SQLException
+ {
+ if (result == null)
+ return 0;
+ return ((org.postgresql.ResultSet) result).getInsertedOID();
+ }
+
+ /**
+ * getResultSet returns the current result as a ResultSet. It
+ * should only be called once per result.
+ *
+ * @return the current result set; null if there are no more
+ * @exception SQLException if a database access error occurs (why?)
+ */
+ public java.sql.ResultSet getResultSet() throws SQLException
+ {
+ if (result != null && ((org.postgresql.ResultSet) result).reallyResultSet())
+ return result;
+ return null;
+ }
+
+ /**
+ * In many cases, it is desirable to immediately release a
+ * Statement's database and JDBC resources instead of waiting
+ * for this to happen when it is automatically closed. The
+ * close method provides this immediate release.
+ *
+ * <p><B>Note:</B> A Statement is automatically closed when it is
+ * garbage collected. When a Statement is closed, its current
+ * ResultSet, if one exists, is also closed.
+ *
+ * @exception SQLException if a database access error occurs (why?)
+ */
+ public void close() throws SQLException
+ {
+ // Force the ResultSet to close
+ java.sql.ResultSet rs = getResultSet();
+ if (rs != null)
+ rs.close();
+
+ // Disasociate it from us (For Garbage Collection)
+ result = null;
+ }
+
+ /**
+ * Filter the SQL string of Java SQL Escape clauses.
+ *
+ * Currently implemented Escape clauses are those mentioned in 11.3
+ * in the specification. Basically we look through the sql string for
+ * {d xxx}, {t xxx} or {ts xxx} in non-string sql code. When we find
+ * them, we just strip the escape part leaving only the xxx part.
+ * So, something like "select * from x where d={d '2001-10-09'}" would
+ * return "select * from x where d= '2001-10-09'".
+ */
+ protected static String escapeSQL(String sql)
+ {
+ // Since escape codes can only appear in SQL CODE, we keep track
+ // of if we enter a string or not.
+ StringBuffer newsql = new StringBuffer();
+ short state = IN_SQLCODE;
+
+ int i = -1;
+ int len = sql.length();
+ while (++i < len)
+ {
+ char c = sql.charAt(i);
+ switch (state)
+ {
+ case IN_SQLCODE:
+ if (c == '\'') // start of a string?
+ state = IN_STRING;
+ else if (c == '{') // start of an escape code?
+ if (i + 1 < len)
+ {
+ char next = sql.charAt(i + 1);
+ if (next == 'd')
+ {
+ state = ESC_TIMEDATE;
+ i++;
+ break;
+ }
+ else if (next == 't')
+ {
+ state = ESC_TIMEDATE;
+ i += (i + 2 < len && sql.charAt(i + 2) == 's') ? 2 : 1;
+ break;
+ }
+ }
+ newsql.append(c);
+ break;
+
+ case IN_STRING:
+ if (c == '\'') // end of string?
+ state = IN_SQLCODE;
+ else if (c == '\\') // a backslash?
+ state = BACKSLASH;
+
+ newsql.append(c);
+ break;
+
+ case BACKSLASH:
+ state = IN_STRING;
+
+ newsql.append(c);
+ break;
+
+ case ESC_TIMEDATE:
+ if (c == '}')
+ state = IN_SQLCODE; // end of escape code.
+ else
+ newsql.append(c);
+ break;
+ } // end switch
+ }
+
+ return newsql.toString();
+ }
}
diff --git a/src/interfaces/jdbc/org/postgresql/core/BytePoolDim1.java b/src/interfaces/jdbc/org/postgresql/core/BytePoolDim1.java
index e78f46b4af2..0f441047222 100644
--- a/src/interfaces/jdbc/org/postgresql/core/BytePoolDim1.java
+++ b/src/interfaces/jdbc/org/postgresql/core/BytePoolDim1.java
@@ -4,92 +4,98 @@ package org.postgresql.core;
* A simple and efficient class to pool one dimensional byte arrays
* of different sizes.
*/
-public class BytePoolDim1 {
+public class BytePoolDim1
+{
- /**
- * The maximum size of the array we manage.
- */
- int maxsize = 256;
- /**
- * The pools not currently in use
- */
- ObjectPool notusemap[] = new ObjectPool[maxsize+1];
- /**
- * The pools currently in use
- */
- ObjectPool inusemap[] = new ObjectPool[maxsize+1];
- /**
- *
- */
- byte binit[][] = new byte[maxsize+1][0];
+ /**
+ * The maximum size of the array we manage.
+ */
+ int maxsize = 256;
+ /**
+ * The pools not currently in use
+ */
+ ObjectPool notusemap[] = new ObjectPool[maxsize + 1];
+ /**
+ * The pools currently in use
+ */
+ ObjectPool inusemap[] = new ObjectPool[maxsize + 1];
+ /**
+ *
+ */
+ byte binit[][] = new byte[maxsize + 1][0];
- /**
- * Construct a new pool
- */
- public BytePoolDim1(){
- for(int i = 0; i <= maxsize; i++){
- binit[i] = new byte[i];
- inusemap[i] = new SimpleObjectPool();
- notusemap[i] = new SimpleObjectPool();
+ /**
+ * Construct a new pool
+ */
+ public BytePoolDim1()
+ {
+ for (int i = 0; i <= maxsize; i++)
+ {
+ binit[i] = new byte[i];
+ inusemap[i] = new SimpleObjectPool();
+ notusemap[i] = new SimpleObjectPool();
+ }
}
- }
- /**
- * Allocate a byte[] of a specified size and put it in the pool. If it's
- * larger than maxsize then it is not pooled.
- * @return the byte[] allocated
- */
- public byte[] allocByte(int size) {
- // for now until the bug can be removed
- return new byte[size];
- /*
- // Don't pool if >maxsize
- if(size > maxsize){
- return new byte[size];
+ /**
+ * Allocate a byte[] of a specified size and put it in the pool. If it's
+ * larger than maxsize then it is not pooled.
+ * @return the byte[] allocated
+ */
+ public byte[] allocByte(int size)
+ {
+ // for now until the bug can be removed
+ return new byte[size];
+ /*
+ // Don't pool if >maxsize
+ if(size > maxsize){
+ return new byte[size];
}
- ObjectPool not_usel = notusemap[size];
- ObjectPool in_usel = inusemap[size];
- byte b[] = null;
+ ObjectPool not_usel = notusemap[size];
+ ObjectPool in_usel = inusemap[size];
+ byte b[] = null;
- // Fetch from the unused pool if available otherwise allocate a new
- // now array
- if(!not_usel.isEmpty()) {
- Object o = not_usel.remove();
- b = (byte[]) o;
+ // Fetch from the unused pool if available otherwise allocate a new
+ // now array
+ if(!not_usel.isEmpty()) {
+ Object o = not_usel.remove();
+ b = (byte[]) o;
} else
- b = new byte[size];
- in_usel.add(b);
+ b = new byte[size];
+ in_usel.add(b);
- return b;
- */
- }
+ return b;
+ */
+ }
- /**
- * Release an array
- * @param b byte[] to release
- */
- public void release(byte[] b) {
- // If it's larger than maxsize then we don't touch it
- if(b.length>maxsize)
- return;
+ /**
+ * Release an array
+ * @param b byte[] to release
+ */
+ public void release(byte[] b)
+ {
+ // If it's larger than maxsize then we don't touch it
+ if (b.length > maxsize)
+ return ;
- ObjectPool not_usel = notusemap[b.length];
- ObjectPool in_usel = inusemap[b.length];
+ ObjectPool not_usel = notusemap[b.length];
+ ObjectPool in_usel = inusemap[b.length];
- in_usel.remove(b);
- not_usel.add(b);
- }
+ in_usel.remove(b);
+ not_usel.add(b);
+ }
- /**
- * Deallocate all
- * @deprecated Real bad things happen if this is called!
- */
- public void deallocate() {
- //for(int i = 0; i <= maxsize; i++){
- // notusemap[i].addAll(inusemap[i]);
- // inusemap[i].clear();
- //}
- }
+ /**
+ * Deallocate all
+ * @deprecated Real bad things happen if this is called!
+ */
+ public void deallocate()
+ {
+ //for(int i = 0; i <= maxsize; i++){
+ // notusemap[i].addAll(inusemap[i]);
+ // inusemap[i].clear();
+ //}
+ }
}
diff --git a/src/interfaces/jdbc/org/postgresql/core/BytePoolDim2.java b/src/interfaces/jdbc/org/postgresql/core/BytePoolDim2.java
index 0eb508171f6..d330af40ea0 100644
--- a/src/interfaces/jdbc/org/postgresql/core/BytePoolDim2.java
+++ b/src/interfaces/jdbc/org/postgresql/core/BytePoolDim2.java
@@ -1,62 +1,69 @@
package org.postgresql.core;
-public class BytePoolDim2 {
- int maxsize = 32;
- ObjectPool notusemap[] = new ObjectPool[maxsize+1];
- ObjectPool inusemap[] = new ObjectPool[maxsize+1];
-
- public BytePoolDim2(){
- for(int i = 0; i <= maxsize; i++){
- inusemap[i] = new SimpleObjectPool();
- notusemap[i] = new SimpleObjectPool();
+public class BytePoolDim2
+{
+ int maxsize = 32;
+ ObjectPool notusemap[] = new ObjectPool[maxsize + 1];
+ ObjectPool inusemap[] = new ObjectPool[maxsize + 1];
+
+ public BytePoolDim2()
+ {
+ for (int i = 0; i <= maxsize; i++)
+ {
+ inusemap[i] = new SimpleObjectPool();
+ notusemap[i] = new SimpleObjectPool();
+ }
}
- }
-
- public byte[][] allocByte(int size){
- // For now until the bug can be removed
- return new byte[size][0];
- /*
- if(size > maxsize){
- return new byte[size][0];
+
+ public byte[][] allocByte(int size)
+ {
+ // For now until the bug can be removed
+ return new byte[size][0];
+ /*
+ if(size > maxsize){
+ return new byte[size][0];
}
- ObjectPool not_usel = notusemap[size];
- ObjectPool in_usel = inusemap[size];
+ ObjectPool not_usel = notusemap[size];
+ ObjectPool in_usel = inusemap[size];
- byte b[][] = null;
+ byte b[][] = null;
- if(!not_usel.isEmpty()) {
- Object o = not_usel.remove();
- b = (byte[][]) o;
+ if(!not_usel.isEmpty()) {
+ Object o = not_usel.remove();
+ b = (byte[][]) o;
} else
- b = new byte[size][0];
- in_usel.add(b);
- return b;
- */
- }
-
- public void release(byte[][] b){
- if(b.length > maxsize){
- return;
+ b = new byte[size][0];
+ in_usel.add(b);
+ return b;
+ */
+ }
+
+ public void release(byte[][] b)
+ {
+ if (b.length > maxsize)
+ {
+ return ;
+ }
+ ObjectPool not_usel = notusemap[b.length];
+ ObjectPool in_usel = inusemap[b.length];
+
+ in_usel.remove(b);
+ not_usel.add(b);
+ }
+
+ /**
+ * Deallocate the object cache.
+ * PM 17/01/01: Commented out this code as it blows away any hope of
+ * multiple queries on the same connection. I'll redesign the allocation
+ * code to use some form of Statement context, so the buffers are per
+ * Statement and not per Connection/PG_Stream as it is now.
+ */
+ public void deallocate()
+ {
+ //for(int i = 0; i <= maxsize; i++){
+ // notusemap[i].addAll(inusemap[i]);
+ // inusemap[i].clear();
+ //}
}
- ObjectPool not_usel = notusemap[b.length];
- ObjectPool in_usel = inusemap[b.length];
-
- in_usel.remove(b);
- not_usel.add(b);
- }
-
- /**
- * Deallocate the object cache.
- * PM 17/01/01: Commented out this code as it blows away any hope of
- * multiple queries on the same connection. I'll redesign the allocation
- * code to use some form of Statement context, so the buffers are per
- * Statement and not per Connection/PG_Stream as it is now.
- */
- public void deallocate(){
- //for(int i = 0; i <= maxsize; i++){
- // notusemap[i].addAll(inusemap[i]);
- // inusemap[i].clear();
- //}
- }
}
diff --git a/src/interfaces/jdbc/org/postgresql/core/Encoding.java b/src/interfaces/jdbc/org/postgresql/core/Encoding.java
index 1f03d8f1e10..11923aee2aa 100644
--- a/src/interfaces/jdbc/org/postgresql/core/Encoding.java
+++ b/src/interfaces/jdbc/org/postgresql/core/Encoding.java
@@ -8,173 +8,213 @@ import org.postgresql.util.*;
/**
* Converts to and from the character encoding used by the backend.
*
- * $Id: Encoding.java,v 1.2 2001/10/16 20:07:17 barry Exp $
+ * $Id: Encoding.java,v 1.3 2001/10/25 05:59:59 momjian Exp $
*/
-public class Encoding {
-
- private static final Encoding DEFAULT_ENCODING = new Encoding(null);
-
- /**
- * Preferred JVM encodings for backend encodings.
- */
- private static final Hashtable encodings = new Hashtable();
-
- static {
- //Note: this list should match the set of supported server
- // encodings found in backend/util/mb/encnames.c
- encodings.put("SQL_ASCII", new String[] { "ASCII", "us-ascii" });
- encodings.put("UNICODE", new String[] { "UTF-8", "UTF8" });
- encodings.put("LATIN1", new String[] { "ISO8859_1" });
- encodings.put("LATIN2", new String[] { "ISO8859_2" });
- encodings.put("LATIN3", new String[] { "ISO8859_3" });
- encodings.put("LATIN4", new String[] { "ISO8859_4" });
- encodings.put("ISO_8859_5", new String[] { "ISO8859_5" });
- encodings.put("ISO_8859_6", new String[] { "ISO8859_6" });
- encodings.put("ISO_8859_7", new String[] { "ISO8859_7" });
- encodings.put("ISO_8859_8", new String[] { "ISO8859_8" });
- encodings.put("LATIN5", new String[] { "ISO8859_9" });
- encodings.put("LATIN7", new String[] { "ISO8859_13" });
- encodings.put("LATIN9", new String[] { "ISO8859_15_FDIS" });
- encodings.put("EUC_JP", new String[] { "EUC_JP" });
- encodings.put("EUC_CN", new String[] { "EUC_CN" });
- encodings.put("EUC_KR", new String[] { "EUC_KR" });
- encodings.put("EUC_TW", new String[] { "EUC_TW" });
- encodings.put("SJIS", new String[] { "SJIS" });
- encodings.put("BIG5", new String[] { "Big5" });
- encodings.put("WIN1250", new String[] { "Cp1250" });
- encodings.put("WIN", new String[] { "Cp1251" });
- encodings.put("ALT", new String[] { "Cp866" });
- // We prefer KOI8-U, since it is a superset of KOI8-R.
- encodings.put("KOI8", new String[] { "KOI8_U", "KOI8_R" });
- // If the database isn't encoding-aware then we can't have
- // any preferred encodings.
- encodings.put("UNKNOWN", new String[0]);
- // The following encodings do not have a java equivalent
- encodings.put("MULE_INTERNAL", new String[0]);
- encodings.put("LATIN6", new String[0]);
- encodings.put("LATIN8", new String[0]);
- encodings.put("LATIN10", new String[0]);
- }
-
- private final String encoding;
-
- private Encoding(String encoding) {
- this.encoding = encoding;
- }
-
- /**
- * Get an Encoding for from the given database encoding and
- * the encoding passed in by the user.
- */
- public static Encoding getEncoding(String databaseEncoding,
- String passedEncoding)
- {
- if (passedEncoding != null) {
- if (isAvailable(passedEncoding)) {
- return new Encoding(passedEncoding);
- } else {
+public class Encoding
+{
+
+ private static final Encoding DEFAULT_ENCODING = new Encoding(null);
+
+ /**
+ * Preferred JVM encodings for backend encodings.
+ */
+ private static final Hashtable encodings = new Hashtable();
+
+ static {
+ //Note: this list should match the set of supported server
+ // encodings found in backend/util/mb/encnames.c
+ encodings.put("SQL_ASCII", new String[] { "ASCII", "us-ascii" });
+ encodings.put("UNICODE", new String[] { "UTF-8", "UTF8" });
+ encodings.put("LATIN1", new String[] { "ISO8859_1" });
+ encodings.put("LATIN2", new String[] { "ISO8859_2" });
+ encodings.put("LATIN3", new String[] { "ISO8859_3" });
+ encodings.put("LATIN4", new String[] { "ISO8859_4" });
+ encodings.put("ISO_8859_5", new String[] { "ISO8859_5" });
+ encodings.put("ISO_8859_6", new String[] { "ISO8859_6" });
+ encodings.put("ISO_8859_7", new String[] { "ISO8859_7" });
+ encodings.put("ISO_8859_8", new String[] { "ISO8859_8" });
+ encodings.put("LATIN5", new String[] { "ISO8859_9" });
+ encodings.put("LATIN7", new String[] { "ISO8859_13" });
+ encodings.put("LATIN9", new String[] { "ISO8859_15_FDIS" });
+ encodings.put("EUC_JP", new String[] { "EUC_JP" });
+ encodings.put("EUC_CN", new String[] { "EUC_CN" });
+ encodings.put("EUC_KR", new String[] { "EUC_KR" });
+ encodings.put("EUC_TW", new String[] { "EUC_TW" });
+ encodings.put("SJIS", new String[] { "SJIS" });
+ encodings.put("BIG5", new String[] { "Big5" });
+ encodings.put("WIN1250", new String[] { "Cp1250" });
+ encodings.put("WIN", new String[] { "Cp1251" });
+ encodings.put("ALT", new String[] { "Cp866" });
+ // We prefer KOI8-U, since it is a superset of KOI8-R.
+ encodings.put("KOI8", new String[] { "KOI8_U", "KOI8_R" });
+ // If the database isn't encoding-aware then we can't have
+ // any preferred encodings.
+ encodings.put("UNKNOWN", new String[0]);
+ // The following encodings do not have a java equivalent
+ encodings.put("MULE_INTERNAL", new String[0]);
+ encodings.put("LATIN6", new String[0]);
+ encodings.put("LATIN8", new String[0]);
+ encodings.put("LATIN10", new String[0]);
+ }
+
+ private final String encoding;
+
+ private Encoding(String encoding)
+ {
+ this.encoding = encoding;
+ }
+
+ /**
+ * Get an Encoding for from the given database encoding and
+ * the encoding passed in by the user.
+ */
+ public static Encoding getEncoding(String databaseEncoding,
+ String passedEncoding)
+ {
+ if (passedEncoding != null)
+ {
+ if (isAvailable(passedEncoding))
+ {
+ return new Encoding(passedEncoding);
+ }
+ else
+ {
+ return defaultEncoding();
+ }
+ }
+ else
+ {
+ return encodingForDatabaseEncoding(databaseEncoding);
+ }
+ }
+
+ /**
+ * Get an Encoding matching the given database encoding.
+ */
+ private static Encoding encodingForDatabaseEncoding(String databaseEncoding)
+ {
+ // If the backend encoding is known and there is a suitable
+ // encoding in the JVM we use that. Otherwise we fall back
+ // to the default encoding of the JVM.
+
+ if (encodings.containsKey(databaseEncoding))
+ {
+ String[] candidates = (String[]) encodings.get(databaseEncoding);
+ for (int i = 0; i < candidates.length; i++)
+ {
+ if (isAvailable(candidates[i]))
+ {
+ return new Encoding(candidates[i]);
+ }
+ }
+ }
return defaultEncoding();
- }
- } else {
- return encodingForDatabaseEncoding(databaseEncoding);
}
- }
-
- /**
- * Get an Encoding matching the given database encoding.
- */
- private static Encoding encodingForDatabaseEncoding(String databaseEncoding) {
- // If the backend encoding is known and there is a suitable
- // encoding in the JVM we use that. Otherwise we fall back
- // to the default encoding of the JVM.
-
- if (encodings.containsKey(databaseEncoding)) {
- String[] candidates = (String[]) encodings.get(databaseEncoding);
- for (int i = 0; i < candidates.length; i++) {
- if (isAvailable(candidates[i])) {
- return new Encoding(candidates[i]);
+
+ /**
+ * Name of the (JVM) encoding used.
+ */
+ public String name()
+ {
+ return encoding;
+ }
+
+ /**
+ * Encode a string to an array of bytes.
+ */
+ public byte[] encode(String s) throws SQLException
+ {
+ try
+ {
+ if (encoding == null)
+ {
+ return s.getBytes();
+ }
+ else
+ {
+ return s.getBytes(encoding);
+ }
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new PSQLException("postgresql.stream.encoding", e);
+ }
+ }
+
+ /**
+ * Decode an array of bytes into a string.
+ */
+ public String decode(byte[] encodedString, int offset, int length) throws SQLException
+ {
+ try
+ {
+ if (encoding == null)
+ {
+ return new String(encodedString, offset, length);
+ }
+ else
+ {
+ return new String(encodedString, offset, length, encoding);
+ }
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new PSQLException("postgresql.stream.encoding", e);
}
- }
}
- return defaultEncoding();
- }
-
- /**
- * Name of the (JVM) encoding used.
- */
- public String name() {
- return encoding;
- }
-
- /**
- * Encode a string to an array of bytes.
- */
- public byte[] encode(String s) throws SQLException {
- try {
- if (encoding == null) {
- return s.getBytes();
- } else {
- return s.getBytes(encoding);
- }
- } catch (UnsupportedEncodingException e) {
- throw new PSQLException("postgresql.stream.encoding", e);
+
+ /**
+ * Decode an array of bytes into a string.
+ */
+ public String decode(byte[] encodedString) throws SQLException
+ {
+ return decode(encodedString, 0, encodedString.length);
}
- }
-
- /**
- * Decode an array of bytes into a string.
- */
- public String decode(byte[] encodedString, int offset, int length) throws SQLException {
- try {
- if (encoding == null) {
- return new String(encodedString, offset, length);
- } else {
- return new String(encodedString, offset, length, encoding);
- }
- } catch (UnsupportedEncodingException e) {
- throw new PSQLException("postgresql.stream.encoding", e);
+
+ /**
+ * Get a Reader that decodes the given InputStream.
+ */
+ public Reader getDecodingReader(InputStream in) throws SQLException
+ {
+ try
+ {
+ if (encoding == null)
+ {
+ return new InputStreamReader(in);
+ }
+ else
+ {
+ return new InputStreamReader(in, encoding);
+ }
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new PSQLException("postgresql.res.encoding", e);
+ }
}
- }
-
- /**
- * Decode an array of bytes into a string.
- */
- public String decode(byte[] encodedString) throws SQLException {
- return decode(encodedString, 0, encodedString.length);
- }
-
- /**
- * Get a Reader that decodes the given InputStream.
- */
- public Reader getDecodingReader(InputStream in) throws SQLException {
- try {
- if (encoding == null) {
- return new InputStreamReader(in);
- } else {
- return new InputStreamReader(in, encoding);
- }
- } catch (UnsupportedEncodingException e) {
- throw new PSQLException("postgresql.res.encoding", e);
+
+ /**
+ * Get an Encoding using the default encoding for the JVM.
+ */
+ public static Encoding defaultEncoding()
+ {
+ return DEFAULT_ENCODING;
}
- }
-
- /**
- * Get an Encoding using the default encoding for the JVM.
- */
- public static Encoding defaultEncoding() {
- return DEFAULT_ENCODING;
- }
-
- /**
- * Test if an encoding is available in the JVM.
- */
- private static boolean isAvailable(String encodingName) {
- try {
- "DUMMY".getBytes(encodingName);
- return true;
- } catch (UnsupportedEncodingException e) {
- return false;
+
+ /**
+ * Test if an encoding is available in the JVM.
+ */
+ private static boolean isAvailable(String encodingName)
+ {
+ try
+ {
+ "DUMMY".getBytes(encodingName);
+ return true;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ return false;
+ }
}
- }
}
diff --git a/src/interfaces/jdbc/org/postgresql/core/MemoryPool.java b/src/interfaces/jdbc/org/postgresql/core/MemoryPool.java
index 1e83d76be2c..4c0996ba58f 100644
--- a/src/interfaces/jdbc/org/postgresql/core/MemoryPool.java
+++ b/src/interfaces/jdbc/org/postgresql/core/MemoryPool.java
@@ -3,16 +3,17 @@ package org.postgresql.core;
/**
* This interface defines the methods to access the memory pool classes.
*/
-public interface MemoryPool {
- /**
- * Allocate an array from the pool
- * @return byte[] allocated
- */
- public byte[] allocByte(int size);
+public interface MemoryPool
+{
+ /**
+ * Allocate an array from the pool
+ * @return byte[] allocated
+ */
+ public byte[] allocByte(int size);
- /**
- * Frees an object back to the pool
- * @param o Object to release
- */
- public void release(Object o);
-} \ No newline at end of file
+ /**
+ * Frees an object back to the pool
+ * @param o Object to release
+ */
+ public void release(Object o);
+}
diff --git a/src/interfaces/jdbc/org/postgresql/core/ObjectPool.java b/src/interfaces/jdbc/org/postgresql/core/ObjectPool.java
index 5053c85c595..646f233e0c9 100644
--- a/src/interfaces/jdbc/org/postgresql/core/ObjectPool.java
+++ b/src/interfaces/jdbc/org/postgresql/core/ObjectPool.java
@@ -6,43 +6,44 @@ package org.postgresql.core;
* other for jdk1.2+
*/
-public interface ObjectPool {
- /**
- * Adds an object to the pool
- * @param o Object to add
- */
- public void add(Object o);
-
- /**
- * Removes an object from the pool
- * @param o Object to remove
- */
- public void remove(Object o);
-
- /**
- * Removes the top object from the pool
- * @return Object from the top.
- */
- public Object remove();
-
- /**
- * @return true if the pool is empty
- */
- public boolean isEmpty();
-
- /**
- * @return the number of objects in the pool
- */
- public int size();
-
- /**
- * Adds all objects in one pool to this one
- * @param pool The pool to take the objects from
- */
- public void addAll(ObjectPool pool);
-
- /**
- * Clears the pool of all objects
- */
- public void clear();
+public interface ObjectPool
+{
+ /**
+ * Adds an object to the pool
+ * @param o Object to add
+ */
+ public void add(Object o);
+
+ /**
+ * Removes an object from the pool
+ * @param o Object to remove
+ */
+ public void remove(Object o);
+
+ /**
+ * Removes the top object from the pool
+ * @return Object from the top.
+ */
+ public Object remove();
+
+ /**
+ * @return true if the pool is empty
+ */
+ public boolean isEmpty();
+
+ /**
+ * @return the number of objects in the pool
+ */
+ public int size();
+
+ /**
+ * Adds all objects in one pool to this one
+ * @param pool The pool to take the objects from
+ */
+ public void addAll(ObjectPool pool);
+
+ /**
+ * Clears the pool of all objects
+ */
+ public void clear();
}
diff --git a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java b/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java
index 318daa84f45..1bb917d3724 100644
--- a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java
+++ b/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java
@@ -13,176 +13,195 @@ import org.postgresql.util.PSQLException;
* <p>The lifetime of a QueryExecutor object is from sending the query
* until the response has been received from the backend.
*
- * $Id: QueryExecutor.java,v 1.2 2001/10/09 20:47:35 barry Exp $
+ * $Id: QueryExecutor.java,v 1.3 2001/10/25 05:59:59 momjian Exp $
*/
-public class QueryExecutor {
-
- private final String sql;
- private final java.sql.Statement statement;
- private final PG_Stream pg_stream;
- private final org.postgresql.Connection connection;
-
- public QueryExecutor(String sql,
- java.sql.Statement statement,
- PG_Stream pg_stream,
- org.postgresql.Connection connection)
- throws SQLException
- {
- this.sql = sql;
- this.statement = statement;
- this.pg_stream = pg_stream;
- this.connection = connection;
-
- if (statement != null)
- maxRows = statement.getMaxRows();
- else
- maxRows = 0;
- }
-
- private Field[] fields = null;
- private Vector tuples = new Vector();
- private boolean binaryCursor = false;
- private String status = null;
- private int update_count = 1;
- private int insert_oid = 0;
- private int maxRows;
-
- /**
- * Execute a query on the backend.
- */
- public java.sql.ResultSet execute() throws SQLException {
-
- int fqp = 0;
- boolean hfr = false;
-
- synchronized(pg_stream) {
-
- sendQuery(sql);
-
- while (!hfr || fqp > 0) {
- int c = pg_stream.ReceiveChar();
-
- switch (c)
- {
- case 'A': // Asynchronous Notify
- int pid = pg_stream.ReceiveInteger(4);
- String msg = pg_stream.ReceiveString(connection.getEncoding());
- break;
- case 'B': // Binary Data Transfer
- receiveTuple(true);
- break;
- case 'C': // Command Status
- receiveCommandStatus();
-
- if (fields != null)
- hfr = true;
- else {
- sendQuery(" ");
- fqp++;
- }
- break;
- case 'D': // Text Data Transfer
- receiveTuple(false);
- break;
- case 'E': // Error Message
- throw new SQLException(pg_stream.ReceiveString(connection.getEncoding()));
- case 'I': // Empty Query
- int t = pg_stream.ReceiveChar();
- if (t != 0)
- throw new PSQLException("postgresql.con.garbled");
-
- if (fqp > 0)
- fqp--;
- if (fqp == 0)
- hfr = true;
- break;
- case 'N': // Error Notification
- connection.addWarning(pg_stream.ReceiveString(connection.getEncoding()));
- break;
- case 'P': // Portal Name
- String pname = pg_stream.ReceiveString(connection.getEncoding());
- break;
- case 'T': // MetaData Field Description
- receiveFields();
- break;
- case 'Z': // backend ready for query, ignore for now :-)
- break;
- default:
- throw new PSQLException("postgresql.con.type",
- new Character((char) c));
- }
- }
- return connection.getResultSet(connection, statement, fields, tuples, status, update_count, insert_oid, binaryCursor);
- }
- }
-
- /**
- * Send a query to the backend.
- */
- private void sendQuery(String query) throws SQLException {
- try {
- pg_stream.SendChar('Q');
- pg_stream.Send(connection.getEncoding().encode(query));
- pg_stream.SendChar(0);
- pg_stream.flush();
-
- } catch (IOException e) {
- throw new PSQLException("postgresql.con.ioerror", e);
- }
- }
-
- /**
- * Receive a tuple from the backend.
- *
- * @param isBinary set if the tuple should be treated as binary data
- */
- private void receiveTuple(boolean isBinary) throws SQLException {
- if (fields == null)
- throw new PSQLException("postgresql.con.tuple");
- Object tuple = pg_stream.ReceiveTuple(fields.length, isBinary);
- if (isBinary) binaryCursor = true;
- if (maxRows == 0 || tuples.size() < maxRows)
- tuples.addElement(tuple);
- }
-
- /**
- * Receive command status from the backend.
- */
- private void receiveCommandStatus() throws SQLException {
-
- status = pg_stream.ReceiveString(connection.getEncoding());
-
- try {
- // Now handle the update count correctly.
- if (status.startsWith("INSERT") || status.startsWith("UPDATE") || status.startsWith("DELETE") || status.startsWith("MOVE")) {
- update_count = Integer.parseInt(status.substring(1 + status.lastIndexOf(' ')));
- }
- if (status.startsWith("INSERT")) {
- insert_oid = Integer.parseInt(status.substring(1 + status.indexOf(' '),
- status.lastIndexOf(' ')));
- }
- } catch (NumberFormatException nfe) {
- throw new PSQLException("postgresql.con.fathom", status);
- }
- }
-
- /**
- * Receive the field descriptions from the back end.
- */
- private void receiveFields() throws SQLException {
- if (fields != null)
- throw new PSQLException("postgresql.con.multres");
-
- int size = pg_stream.ReceiveIntegerR(2);
- fields = new Field[size];
-
- for (int i = 0; i < fields.length; i++) {
- String typeName = pg_stream.ReceiveString(connection.getEncoding());
- int typeOid = pg_stream.ReceiveIntegerR(4);
- int typeLength = pg_stream.ReceiveIntegerR(2);
- int typeModifier = pg_stream.ReceiveIntegerR(4);
- fields[i] = new Field(connection, typeName, typeOid, typeLength, typeModifier);
- }
- }
+public class QueryExecutor
+{
+
+ private final String sql;
+ private final java.sql.Statement statement;
+ private final PG_Stream pg_stream;
+ private final org.postgresql.Connection connection;
+
+ public QueryExecutor(String sql,
+ java.sql.Statement statement,
+ PG_Stream pg_stream,
+ org.postgresql.Connection connection)
+ throws SQLException
+ {
+ this.sql = sql;
+ this.statement = statement;
+ this.pg_stream = pg_stream;
+ this.connection = connection;
+
+ if (statement != null)
+ maxRows = statement.getMaxRows();
+ else
+ maxRows = 0;
+ }
+
+ private Field[] fields = null;
+ private Vector tuples = new Vector();
+ private boolean binaryCursor = false;
+ private String status = null;
+ private int update_count = 1;
+ private int insert_oid = 0;
+ private int maxRows;
+
+ /**
+ * Execute a query on the backend.
+ */
+ public java.sql.ResultSet execute() throws SQLException
+ {
+
+ int fqp = 0;
+ boolean hfr = false;
+
+ synchronized (pg_stream)
+ {
+
+ sendQuery(sql);
+
+ while (!hfr || fqp > 0)
+ {
+ int c = pg_stream.ReceiveChar();
+
+ switch (c)
+ {
+ case 'A': // Asynchronous Notify
+ int pid = pg_stream.ReceiveInteger(4);
+ String msg = pg_stream.ReceiveString(connection.getEncoding());
+ break;
+ case 'B': // Binary Data Transfer
+ receiveTuple(true);
+ break;
+ case 'C': // Command Status
+ receiveCommandStatus();
+
+ if (fields != null)
+ hfr = true;
+ else
+ {
+ sendQuery(" ");
+ fqp++;
+ }
+ break;
+ case 'D': // Text Data Transfer
+ receiveTuple(false);
+ break;
+ case 'E': // Error Message
+ throw new SQLException(pg_stream.ReceiveString(connection.getEncoding()));
+ case 'I': // Empty Query
+ int t = pg_stream.ReceiveChar();
+ if (t != 0)
+ throw new PSQLException("postgresql.con.garbled");
+
+ if (fqp > 0)
+ fqp--;
+ if (fqp == 0)
+ hfr = true;
+ break;
+ case 'N': // Error Notification
+ connection.addWarning(pg_stream.ReceiveString(connection.getEncoding()));
+ break;
+ case 'P': // Portal Name
+ String pname = pg_stream.ReceiveString(connection.getEncoding());
+ break;
+ case 'T': // MetaData Field Description
+ receiveFields();
+ break;
+ case 'Z': // backend ready for query, ignore for now :-)
+ break;
+ default:
+ throw new PSQLException("postgresql.con.type",
+ new Character((char) c));
+ }
+ }
+ return connection.getResultSet(connection, statement, fields, tuples, status, update_count, insert_oid, binaryCursor);
+ }
+ }
+
+ /**
+ * Send a query to the backend.
+ */
+ private void sendQuery(String query) throws SQLException
+ {
+ try
+ {
+ pg_stream.SendChar('Q');
+ pg_stream.Send(connection.getEncoding().encode(query));
+ pg_stream.SendChar(0);
+ pg_stream.flush();
+
+ }
+ catch (IOException e)
+ {
+ throw new PSQLException("postgresql.con.ioerror", e);
+ }
+ }
+
+ /**
+ * Receive a tuple from the backend.
+ *
+ * @param isBinary set if the tuple should be treated as binary data
+ */
+ private void receiveTuple(boolean isBinary) throws SQLException
+ {
+ if (fields == null)
+ throw new PSQLException("postgresql.con.tuple");
+ Object tuple = pg_stream.ReceiveTuple(fields.length, isBinary);
+ if (isBinary)
+ binaryCursor = true;
+ if (maxRows == 0 || tuples.size() < maxRows)
+ tuples.addElement(tuple);
+ }
+
+ /**
+ * Receive command status from the backend.
+ */
+ private void receiveCommandStatus() throws SQLException
+ {
+
+ status = pg_stream.ReceiveString(connection.getEncoding());
+
+ try
+ {
+ // Now handle the update count correctly.
+ if (status.startsWith("INSERT") || status.startsWith("UPDATE") || status.startsWith("DELETE") || status.startsWith("MOVE"))
+ {
+ update_count = Integer.parseInt(status.substring(1 + status.lastIndexOf(' ')));
+ }
+ if (status.startsWith("INSERT"))
+ {
+ insert_oid = Integer.parseInt(status.substring(1 + status.indexOf(' '),
+ status.lastIndexOf(' ')));
+ }
+ }
+ catch (NumberFormatException nfe)
+ {
+ throw new PSQLException("postgresql.con.fathom", status);
+ }
+ }
+
+ /**
+ * Receive the field descriptions from the back end.
+ */
+ private void receiveFields() throws SQLException
+ {
+ if (fields != null)
+ throw new PSQLException("postgresql.con.multres");
+
+ int size = pg_stream.ReceiveIntegerR(2);
+ fields = new Field[size];
+
+ for (int i = 0; i < fields.length; i++)
+ {
+ String typeName = pg_stream.ReceiveString(connection.getEncoding());
+ int typeOid = pg_stream.ReceiveIntegerR(4);
+ int typeLength = pg_stream.ReceiveIntegerR(2);
+ int typeModifier = pg_stream.ReceiveIntegerR(4);
+ fields[i] = new Field(connection, typeName, typeOid, typeLength, typeModifier);
+ }
+ }
}
diff --git a/src/interfaces/jdbc/org/postgresql/core/SimpleObjectPool.java b/src/interfaces/jdbc/org/postgresql/core/SimpleObjectPool.java
index e9d5d9fc6d2..dd5ffe85cad 100644
--- a/src/interfaces/jdbc/org/postgresql/core/SimpleObjectPool.java
+++ b/src/interfaces/jdbc/org/postgresql/core/SimpleObjectPool.java
@@ -8,90 +8,99 @@ package org.postgresql.core;
public class SimpleObjectPool implements ObjectPool
{
- // This was originally in PG_Stream but moved out to fix the major problem
- // where more than one query (usually all the time) overwrote the results
- // of another query.
- int cursize = 0;
- int maxsize = 16;
- Object arr[] = new Object[maxsize];
+ // This was originally in PG_Stream but moved out to fix the major problem
+ // where more than one query (usually all the time) overwrote the results
+ // of another query.
+ int cursize = 0;
+ int maxsize = 16;
+ Object arr[] = new Object[maxsize];
- /**
- * Adds an object to the pool
- * @param o Object to add
- */
- public void add(Object o)
- {
- if(cursize >= maxsize){
- Object newarr[] = new Object[maxsize*2];
- System.arraycopy(arr, 0, newarr, 0, maxsize);
- maxsize = maxsize * 2;
- arr = newarr;
+ /**
+ * Adds an object to the pool
+ * @param o Object to add
+ */
+ public void add(Object o)
+ {
+ if (cursize >= maxsize)
+ {
+ Object newarr[] = new Object[maxsize * 2];
+ System.arraycopy(arr, 0, newarr, 0, maxsize);
+ maxsize = maxsize * 2;
+ arr = newarr;
+ }
+ arr[cursize++] = o;
}
- arr[cursize++] = o;
- }
- /**
- * Removes the top object from the pool
- * @return Object from the top.
- */
- public Object remove(){
- return arr[--cursize];
- }
+ /**
+ * Removes the top object from the pool
+ * @return Object from the top.
+ */
+ public Object remove()
+ {
+ return arr[--cursize];
+ }
- /**
- * Removes the given object from the pool
- * @param o Object to remove
- */
- public void remove(Object o) {
- int p=0;
- while(p<cursize && !arr[p].equals(o))
- p++;
- if(arr[p].equals(o)) {
- // This should be ok as there should be no overlap conflict
- System.arraycopy(arr,p+1,arr,p,cursize-p);
- cursize--;
- }
- }
+ /**
+ * Removes the given object from the pool
+ * @param o Object to remove
+ */
+ public void remove(Object o)
+ {
+ int p = 0;
+ while (p < cursize && !arr[p].equals(o))
+ p++;
+ if (arr[p].equals(o))
+ {
+ // This should be ok as there should be no overlap conflict
+ System.arraycopy(arr, p + 1, arr, p, cursize - p);
+ cursize--;
+ }
+ }
- /**
- * @return true if the pool is empty
- */
- public boolean isEmpty(){
- return cursize == 0;
- }
+ /**
+ * @return true if the pool is empty
+ */
+ public boolean isEmpty()
+ {
+ return cursize == 0;
+ }
- /**
- * @return the number of objects in the pool
- */
- public int size(){
- return cursize;
- }
+ /**
+ * @return the number of objects in the pool
+ */
+ public int size()
+ {
+ return cursize;
+ }
- /**
- * Adds all objects in one pool to this one
- * @param pool The pool to take the objects from
- */
- public void addAll(ObjectPool p){
- SimpleObjectPool pool = (SimpleObjectPool)p;
+ /**
+ * Adds all objects in one pool to this one
+ * @param pool The pool to take the objects from
+ */
+ public void addAll(ObjectPool p)
+ {
+ SimpleObjectPool pool = (SimpleObjectPool)p;
- int srcsize = pool.size();
- if(srcsize == 0)
- return;
- int totalsize = srcsize + cursize;
- if(totalsize > maxsize){
- Object newarr[] = new Object[totalsize*2];
- System.arraycopy(arr, 0, newarr, 0, cursize);
- maxsize = maxsize = totalsize * 2;
- arr = newarr;
+ int srcsize = pool.size();
+ if (srcsize == 0)
+ return ;
+ int totalsize = srcsize + cursize;
+ if (totalsize > maxsize)
+ {
+ Object newarr[] = new Object[totalsize * 2];
+ System.arraycopy(arr, 0, newarr, 0, cursize);
+ maxsize = maxsize = totalsize * 2;
+ arr = newarr;
+ }
+ System.arraycopy(pool.arr, 0, arr, cursize, srcsize);
+ cursize = totalsize;
}
- System.arraycopy(pool.arr, 0, arr, cursize, srcsize);
- cursize = totalsize;
- }
- /**
- * Clears the pool of all objects
- */
- public void clear(){
- cursize = 0;
- }
+ /**
+ * Clears the pool of all objects
+ */
+ public void clear()
+ {
+ cursize = 0;
+ }
}
diff --git a/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java b/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java
index a99bd0c0d16..77460b492c3 100644
--- a/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java
+++ b/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java
@@ -23,266 +23,273 @@ import org.postgresql.util.*;
*/
public class Fastpath
{
- // This maps the functions names to their id's (possible unique just
- // to a connection).
- protected Hashtable func = new Hashtable();
-
- protected org.postgresql.Connection conn; // our connection
- protected org.postgresql.PG_Stream stream; // the network stream
-
- /**
- * Initialises the fastpath system
- *
- * <p><b>Important Notice</b>
- * <br>This is called from org.postgresql.Connection, and should not be called
- * from client code.
- *
- * @param conn org.postgresql.Connection to attach to
- * @param stream The network stream to the backend
- */
- public Fastpath(org.postgresql.Connection conn,org.postgresql.PG_Stream stream)
- {
- this.conn=conn;
- this.stream=stream;
- //DriverManager.println("Fastpath initialised");
- }
-
- /**
- * Send a function call to the PostgreSQL backend
- *
- * @param fnid Function id
- * @param resulttype True if the result is an integer, false for other results
- * @param args FastpathArguments to pass to fastpath
- * @return null if no data, Integer if an integer result, or byte[] otherwise
- * @exception SQLException if a database-access error occurs.
- */
- public Object fastpath(int fnid,boolean resulttype,FastpathArg[] args) throws SQLException
- {
- // added Oct 7 1998 to give us thread safety
- synchronized(stream) {
-
- // send the function call
- try {
- // 70 is 'F' in ASCII. Note: don't use SendChar() here as it adds padding
- // that confuses the backend. The 0 terminates the command line.
- stream.SendInteger(70,1);
- stream.SendInteger(0,1);
+ // This maps the functions names to their id's (possible unique just
+ // to a connection).
+ protected Hashtable func = new Hashtable();
- stream.SendInteger(fnid,4);
- stream.SendInteger(args.length,4);
-
- for(int i=0;i<args.length;i++)
- args[i].send(stream);
-
- // This is needed, otherwise data can be lost
- stream.flush();
-
- } catch(IOException ioe) {
- throw new PSQLException("postgresql.fp.send",new Integer(fnid),ioe);
- }
-
- // Now handle the result
-
- // We should get 'V' on sucess or 'E' on error. Anything else is treated
- // as an error.
- //int in = stream.ReceiveChar();
- //DriverManager.println("ReceiveChar() = "+in+" '"+((char)in)+"'");
- //if(in!='V') {
- //if(in=='E')
- //throw new SQLException(stream.ReceiveString(conn.getEncoding()));
- //throw new SQLException("Fastpath: expected 'V' from backend, got "+((char)in));
- //}
-
- // Now loop, reading the results
- Object result = null; // our result
- while(true) {
- int in = stream.ReceiveChar();
- //DriverManager.println("ReceiveChar() = "+in+" '"+((char)in)+"'");
- switch(in)
+ protected org.postgresql.Connection conn; // our connection
+ protected org.postgresql.PG_Stream stream; // the network stream
+
+ /**
+ * Initialises the fastpath system
+ *
+ * <p><b>Important Notice</b>
+ * <br>This is called from org.postgresql.Connection, and should not be called
+ * from client code.
+ *
+ * @param conn org.postgresql.Connection to attach to
+ * @param stream The network stream to the backend
+ */
+ public Fastpath(org.postgresql.Connection conn, org.postgresql.PG_Stream stream)
{
- case 'V':
- break;
-
- //------------------------------
- // Function returned properly
- //
- case 'G':
- int sz = stream.ReceiveIntegerR(4);
- //DriverManager.println("G: size="+sz); //debug
-
- // Return an Integer if
- if(resulttype)
- result = new Integer(stream.ReceiveIntegerR(sz));
- else {
- byte buf[] = new byte[sz];
- stream.Receive(buf,0,sz);
- result = buf;
- }
- break;
-
- //------------------------------
- // Error message returned
- case 'E':
- throw new PSQLException("postgresql.fp.error",stream.ReceiveString(conn.getEncoding()));
-
- //------------------------------
- // Notice from backend
- case 'N':
- conn.addWarning(stream.ReceiveString(conn.getEncoding()));
- break;
-
- //------------------------------
- // End of results
- //
- // Here we simply return res, which would contain the result
- // processed earlier. If no result, this already contains null
- case '0':
- //DriverManager.println("returning "+result);
- return result;
-
- case 'Z':
- break;
-
- default:
- throw new PSQLException("postgresql.fp.protocol",new Character((char)in));
+ this.conn = conn;
+ this.stream = stream;
+ //DriverManager.println("Fastpath initialised");
+ }
+
+ /**
+ * Send a function call to the PostgreSQL backend
+ *
+ * @param fnid Function id
+ * @param resulttype True if the result is an integer, false for other results
+ * @param args FastpathArguments to pass to fastpath
+ * @return null if no data, Integer if an integer result, or byte[] otherwise
+ * @exception SQLException if a database-access error occurs.
+ */
+ public Object fastpath(int fnid, boolean resulttype, FastpathArg[] args) throws SQLException
+ {
+ // added Oct 7 1998 to give us thread safety
+ synchronized (stream)
+ {
+
+ // send the function call
+ try
+ {
+ // 70 is 'F' in ASCII. Note: don't use SendChar() here as it adds padding
+ // that confuses the backend. The 0 terminates the command line.
+ stream.SendInteger(70, 1);
+ stream.SendInteger(0, 1);
+
+ stream.SendInteger(fnid, 4);
+ stream.SendInteger(args.length, 4);
+
+ for (int i = 0;i < args.length;i++)
+ args[i].send(stream);
+
+ // This is needed, otherwise data can be lost
+ stream.flush();
+
+ }
+ catch (IOException ioe)
+ {
+ throw new PSQLException("postgresql.fp.send", new Integer(fnid), ioe);
+ }
+
+ // Now handle the result
+
+ // We should get 'V' on sucess or 'E' on error. Anything else is treated
+ // as an error.
+ //int in = stream.ReceiveChar();
+ //DriverManager.println("ReceiveChar() = "+in+" '"+((char)in)+"'");
+ //if(in!='V') {
+ //if(in=='E')
+ //throw new SQLException(stream.ReceiveString(conn.getEncoding()));
+ //throw new SQLException("Fastpath: expected 'V' from backend, got "+((char)in));
+ //}
+
+ // Now loop, reading the results
+ Object result = null; // our result
+ while (true)
+ {
+ int in = stream.ReceiveChar();
+ //DriverManager.println("ReceiveChar() = "+in+" '"+((char)in)+"'");
+ switch (in)
+ {
+ case 'V':
+ break;
+
+ //------------------------------
+ // Function returned properly
+ //
+ case 'G':
+ int sz = stream.ReceiveIntegerR(4);
+ //DriverManager.println("G: size="+sz); //debug
+
+ // Return an Integer if
+ if (resulttype)
+ result = new Integer(stream.ReceiveIntegerR(sz));
+ else
+ {
+ byte buf[] = new byte[sz];
+ stream.Receive(buf, 0, sz);
+ result = buf;
+ }
+ break;
+
+ //------------------------------
+ // Error message returned
+ case 'E':
+ throw new PSQLException("postgresql.fp.error", stream.ReceiveString(conn.getEncoding()));
+
+ //------------------------------
+ // Notice from backend
+ case 'N':
+ conn.addWarning(stream.ReceiveString(conn.getEncoding()));
+ break;
+
+ //------------------------------
+ // End of results
+ //
+ // Here we simply return res, which would contain the result
+ // processed earlier. If no result, this already contains null
+ case '0':
+ //DriverManager.println("returning "+result);
+ return result;
+
+ case 'Z':
+ break;
+
+ default:
+ throw new PSQLException("postgresql.fp.protocol", new Character((char)in));
+ }
+ }
+ }
+ }
+
+ /**
+ * Send a function call to the PostgreSQL backend by name.
+ *
+ * Note: the mapping for the procedure name to function id needs to exist,
+ * usually to an earlier call to addfunction().
+ *
+ * This is the prefered method to call, as function id's can/may change
+ * between versions of the backend.
+ *
+ * For an example of how this works, refer to org.postgresql.LargeObject
+ *
+ * @param name Function name
+ * @param resulttype True if the result is an integer, false for other
+ * results
+ * @param args FastpathArguments to pass to fastpath
+ * @return null if no data, Integer if an integer result, or byte[] otherwise
+ * @exception SQLException if name is unknown or if a database-access error
+ * occurs.
+ * @see org.postgresql.LargeObject
+ */
+ public Object fastpath(String name, boolean resulttype, FastpathArg[] args) throws SQLException
+ {
+ //DriverManager.println("Fastpath: calling "+name);
+ return fastpath(getID(name), resulttype, args);
+ }
+
+ /**
+ * This convenience method assumes that the return value is an Integer
+ * @param name Function name
+ * @param args Function arguments
+ * @return integer result
+ * @exception SQLException if a database-access error occurs or no result
+ */
+ public int getInteger(String name, FastpathArg[] args) throws SQLException
+ {
+ Integer i = (Integer)fastpath(name, true, args);
+ if (i == null)
+ throw new PSQLException("postgresql.fp.expint", name);
+ return i.intValue();
+ }
+
+ /**
+ * This convenience method assumes that the return value is an Integer
+ * @param name Function name
+ * @param args Function arguments
+ * @return byte[] array containing result
+ * @exception SQLException if a database-access error occurs or no result
+ */
+ public byte[] getData(String name, FastpathArg[] args) throws SQLException
+ {
+ return (byte[])fastpath(name, false, args);
+ }
+
+ /**
+ * This adds a function to our lookup table.
+ *
+ * <p>User code should use the addFunctions method, which is based upon a
+ * query, rather than hard coding the oid. The oid for a function is not
+ * guaranteed to remain static, even on different servers of the same
+ * version.
+ *
+ * @param name Function name
+ * @param fnid Function id
+ */
+ public void addFunction(String name, int fnid)
+ {
+ func.put(name, new Integer(fnid));
+ }
+
+ /**
+ * This takes a ResultSet containing two columns. Column 1 contains the
+ * function name, Column 2 the oid.
+ *
+ * <p>It reads the entire ResultSet, loading the values into the function
+ * table.
+ *
+ * <p><b>REMEMBER</b> to close() the resultset after calling this!!
+ *
+ * <p><b><em>Implementation note about function name lookups:</em></b>
+ *
+ * <p>PostgreSQL stores the function id's and their corresponding names in
+ * the pg_proc table. To speed things up locally, instead of querying each
+ * function from that table when required, a Hashtable is used. Also, only
+ * the function's required are entered into this table, keeping connection
+ * times as fast as possible.
+ *
+ * <p>The org.postgresql.LargeObject class performs a query upon it's startup,
+ * and passes the returned ResultSet to the addFunctions() method here.
+ *
+ * <p>Once this has been done, the LargeObject api refers to the functions by
+ * name.
+ *
+ * <p>Dont think that manually converting them to the oid's will work. Ok,
+ * they will for now, but they can change during development (there was some
+ * discussion about this for V7.0), so this is implemented to prevent any
+ * unwarranted headaches in the future.
+ *
+ * @param rs ResultSet
+ * @exception SQLException if a database-access error occurs.
+ * @see org.postgresql.LargeObjectManager
+ */
+ public void addFunctions(ResultSet rs) throws SQLException
+ {
+ while (rs.next())
+ {
+ func.put(rs.getString(1), new Integer(rs.getInt(2)));
+ }
+ }
+
+ /**
+ * This returns the function id associated by its name
+ *
+ * <p>If addFunction() or addFunctions() have not been called for this name,
+ * then an SQLException is thrown.
+ *
+ * @param name Function name to lookup
+ * @return Function ID for fastpath call
+ * @exception SQLException is function is unknown.
+ */
+ public int getID(String name) throws SQLException
+ {
+ Integer id = (Integer)func.get(name);
+
+ // may be we could add a lookup to the database here, and store the result
+ // in our lookup table, throwing the exception if that fails.
+ // We must, however, ensure that if we do, any existing ResultSet is
+ // unaffected, otherwise we could break user code.
+ //
+ // so, until we know we can do this (needs testing, on the TODO list)
+ // for now, we throw the exception and do no lookups.
+ if (id == null)
+ throw new PSQLException("postgresql.fp.unknown", name);
+
+ return id.intValue();
}
- }
- }
- }
-
- /**
- * Send a function call to the PostgreSQL backend by name.
- *
- * Note: the mapping for the procedure name to function id needs to exist,
- * usually to an earlier call to addfunction().
- *
- * This is the prefered method to call, as function id's can/may change
- * between versions of the backend.
- *
- * For an example of how this works, refer to org.postgresql.LargeObject
- *
- * @param name Function name
- * @param resulttype True if the result is an integer, false for other
- * results
- * @param args FastpathArguments to pass to fastpath
- * @return null if no data, Integer if an integer result, or byte[] otherwise
- * @exception SQLException if name is unknown or if a database-access error
- * occurs.
- * @see org.postgresql.LargeObject
- */
- public Object fastpath(String name,boolean resulttype,FastpathArg[] args) throws SQLException
- {
- //DriverManager.println("Fastpath: calling "+name);
- return fastpath(getID(name),resulttype,args);
- }
-
- /**
- * This convenience method assumes that the return value is an Integer
- * @param name Function name
- * @param args Function arguments
- * @return integer result
- * @exception SQLException if a database-access error occurs or no result
- */
- public int getInteger(String name,FastpathArg[] args) throws SQLException
- {
- Integer i = (Integer)fastpath(name,true,args);
- if(i==null)
- throw new PSQLException("postgresql.fp.expint",name);
- return i.intValue();
- }
-
- /**
- * This convenience method assumes that the return value is an Integer
- * @param name Function name
- * @param args Function arguments
- * @return byte[] array containing result
- * @exception SQLException if a database-access error occurs or no result
- */
- public byte[] getData(String name,FastpathArg[] args) throws SQLException
- {
- return (byte[])fastpath(name,false,args);
- }
-
- /**
- * This adds a function to our lookup table.
- *
- * <p>User code should use the addFunctions method, which is based upon a
- * query, rather than hard coding the oid. The oid for a function is not
- * guaranteed to remain static, even on different servers of the same
- * version.
- *
- * @param name Function name
- * @param fnid Function id
- */
- public void addFunction(String name,int fnid)
- {
- func.put(name,new Integer(fnid));
- }
-
- /**
- * This takes a ResultSet containing two columns. Column 1 contains the
- * function name, Column 2 the oid.
- *
- * <p>It reads the entire ResultSet, loading the values into the function
- * table.
- *
- * <p><b>REMEMBER</b> to close() the resultset after calling this!!
- *
- * <p><b><em>Implementation note about function name lookups:</em></b>
- *
- * <p>PostgreSQL stores the function id's and their corresponding names in
- * the pg_proc table. To speed things up locally, instead of querying each
- * function from that table when required, a Hashtable is used. Also, only
- * the function's required are entered into this table, keeping connection
- * times as fast as possible.
- *
- * <p>The org.postgresql.LargeObject class performs a query upon it's startup,
- * and passes the returned ResultSet to the addFunctions() method here.
- *
- * <p>Once this has been done, the LargeObject api refers to the functions by
- * name.
- *
- * <p>Dont think that manually converting them to the oid's will work. Ok,
- * they will for now, but they can change during development (there was some
- * discussion about this for V7.0), so this is implemented to prevent any
- * unwarranted headaches in the future.
- *
- * @param rs ResultSet
- * @exception SQLException if a database-access error occurs.
- * @see org.postgresql.LargeObjectManager
- */
- public void addFunctions(ResultSet rs) throws SQLException
- {
- while(rs.next()) {
- func.put(rs.getString(1),new Integer(rs.getInt(2)));
- }
- }
-
- /**
- * This returns the function id associated by its name
- *
- * <p>If addFunction() or addFunctions() have not been called for this name,
- * then an SQLException is thrown.
- *
- * @param name Function name to lookup
- * @return Function ID for fastpath call
- * @exception SQLException is function is unknown.
- */
- public int getID(String name) throws SQLException
- {
- Integer id = (Integer)func.get(name);
-
- // may be we could add a lookup to the database here, and store the result
- // in our lookup table, throwing the exception if that fails.
- // We must, however, ensure that if we do, any existing ResultSet is
- // unaffected, otherwise we could break user code.
- //
- // so, until we know we can do this (needs testing, on the TODO list)
- // for now, we throw the exception and do no lookups.
- if(id==null)
- throw new PSQLException("postgresql.fp.unknown",name);
-
- return id.intValue();
- }
}
diff --git a/src/interfaces/jdbc/org/postgresql/fastpath/FastpathArg.java b/src/interfaces/jdbc/org/postgresql/fastpath/FastpathArg.java
index 87b8475f645..7234df10d80 100644
--- a/src/interfaces/jdbc/org/postgresql/fastpath/FastpathArg.java
+++ b/src/interfaces/jdbc/org/postgresql/fastpath/FastpathArg.java
@@ -22,85 +22,88 @@ import org.postgresql.util.*;
*/
public class FastpathArg
{
- /**
- * Type of argument, true=integer, false=byte[]
- */
- public boolean type;
-
- /**
- * Integer value if type=true
- */
- public int value;
-
- /**
- * Byte value if type=false;
- */
- public byte[] bytes;
-
- /**
- * Constructs an argument that consists of an integer value
- * @param value int value to set
- */
- public FastpathArg(int value)
- {
- type=true;
- this.value=value;
- }
-
- /**
- * Constructs an argument that consists of an array of bytes
- * @param bytes array to store
- */
- public FastpathArg(byte bytes[])
- {
- type=false;
- this.bytes=bytes;
- }
-
- /**
- * Constructs an argument that consists of part of a byte array
- * @param buf source array
- * @param off offset within array
- * @param len length of data to include
- */
- public FastpathArg(byte buf[],int off,int len)
- {
- type=false;
- bytes = new byte[len];
- System.arraycopy(buf,off,bytes,0,len);
- }
-
- /**
- * Constructs an argument that consists of a String.
- * @param s String to store
- */
- public FastpathArg(String s)
- {
- this(s.getBytes());
- }
-
- /**
- * This sends this argument down the network stream.
- *
- * <p>The stream sent consists of the length.int4 then the contents.
- *
- * <p><b>Note:</b> This is called from Fastpath, and cannot be called from
- * client code.
- *
- * @param s output stream
- * @exception IOException if something failed on the network stream
- */
- protected void send(org.postgresql.PG_Stream s) throws IOException
- {
- if(type) {
- // argument is an integer
- s.SendInteger(4,4); // size of an integer
- s.SendInteger(value,4); // integer value of argument
- } else {
- // argument is a byte array
- s.SendInteger(bytes.length,4); // size of array
- s.Send(bytes);
- }
- }
+ /**
+ * Type of argument, true=integer, false=byte[]
+ */
+ public boolean type;
+
+ /**
+ * Integer value if type=true
+ */
+ public int value;
+
+ /**
+ * Byte value if type=false;
+ */
+ public byte[] bytes;
+
+ /**
+ * Constructs an argument that consists of an integer value
+ * @param value int value to set
+ */
+ public FastpathArg(int value)
+ {
+ type = true;
+ this.value = value;
+ }
+
+ /**
+ * Constructs an argument that consists of an array of bytes
+ * @param bytes array to store
+ */
+ public FastpathArg(byte bytes[])
+ {
+ type = false;
+ this.bytes = bytes;
+ }
+
+ /**
+ * Constructs an argument that consists of part of a byte array
+ * @param buf source array
+ * @param off offset within array
+ * @param len length of data to include
+ */
+ public FastpathArg(byte buf[], int off, int len)
+ {
+ type = false;
+ bytes = new byte[len];
+ System.arraycopy(buf, off, bytes, 0, len);
+ }
+
+ /**
+ * Constructs an argument that consists of a String.
+ * @param s String to store
+ */
+ public FastpathArg(String s)
+ {
+ this(s.getBytes());
+ }
+
+ /**
+ * This sends this argument down the network stream.
+ *
+ * <p>The stream sent consists of the length.int4 then the contents.
+ *
+ * <p><b>Note:</b> This is called from Fastpath, and cannot be called from
+ * client code.
+ *
+ * @param s output stream
+ * @exception IOException if something failed on the network stream
+ */
+ protected void send(org.postgresql.PG_Stream s) throws IOException
+ {
+ if (type)
+ {
+ // argument is an integer
+ s.SendInteger(4, 4); // size of an integer
+ s.SendInteger(value, 4); // integer value of argument
+ }
+ else
+ {
+ // argument is a byte array
+ s.SendInteger(bytes.length, 4); // size of array
+ s.Send(bytes);
+ }
+ }
}
diff --git a/src/interfaces/jdbc/org/postgresql/geometric/PGbox.java b/src/interfaces/jdbc/org/postgresql/geometric/PGbox.java
index f092133ad44..baefd2ff109 100644
--- a/src/interfaces/jdbc/org/postgresql/geometric/PGbox.java
+++ b/src/interfaces/jdbc/org/postgresql/geometric/PGbox.java
@@ -7,99 +7,100 @@ import org.postgresql.util.*;
/**
* This represents the box datatype within org.postgresql.
*/
-public class PGbox extends PGobject implements Serializable,Cloneable
+public class PGbox extends PGobject implements Serializable, Cloneable
{
- /**
- * These are the two points.
- */
- public PGpoint point[] = new PGpoint[2];
-
- /**
- * @param x1 first x coordinate
- * @param y1 first y coordinate
- * @param x2 second x coordinate
- * @param y2 second y coordinate
- */
- public PGbox(double x1,double y1,double x2,double y2)
- {
- this();
- this.point[0] = new PGpoint(x1,y1);
- this.point[1] = new PGpoint(x2,y2);
- }
-
- /**
- * @param p1 first point
- * @param p2 second point
- */
- public PGbox(PGpoint p1,PGpoint p2)
- {
- this();
- this.point[0] = p1;
- this.point[1] = p2;
- }
-
- /**
- * @param s Box definition in PostgreSQL syntax
- * @exception SQLException if definition is invalid
- */
- public PGbox(String s) throws SQLException
- {
- this();
- setValue(s);
- }
-
- /**
- * Required constructor
- */
- public PGbox()
- {
- setType("box");
- }
-
- /**
- * This method sets the value of this object. It should be overidden,
- * but still called by subclasses.
- *
- * @param value a string representation of the value of the object
- * @exception SQLException thrown if value is invalid for this type
- */
- public void setValue(String value) throws SQLException
- {
- PGtokenizer t = new PGtokenizer(value,',');
- if(t.getSize() != 2)
- throw new PSQLException("postgresql.geo.box",value);
-
- point[0] = new PGpoint(t.getToken(0));
- point[1] = new PGpoint(t.getToken(1));
- }
-
- /**
- * @param obj Object to compare with
- * @return true if the two boxes are identical
- */
- public boolean equals(Object obj)
- {
- if(obj instanceof PGbox) {
- PGbox p = (PGbox)obj;
- return (p.point[0].equals(point[0]) && p.point[1].equals(point[1])) ||
- (p.point[0].equals(point[1]) && p.point[1].equals(point[0]));
- }
- return false;
- }
-
- /**
- * This must be overidden to allow the object to be cloned
- */
- public Object clone()
- {
- return new PGbox((PGpoint)point[0].clone(),(PGpoint)point[1].clone());
- }
-
- /**
- * @return the PGbox in the syntax expected by org.postgresql
- */
- public String getValue()
- {
- return point[0].toString()+","+point[1].toString();
- }
+ /**
+ * These are the two points.
+ */
+ public PGpoint point[] = new PGpoint[2];
+
+ /**
+ * @param x1 first x coordinate
+ * @param y1 first y coordinate
+ * @param x2 second x coordinate
+ * @param y2 second y coordinate
+ */
+ public PGbox(double x1, double y1, double x2, double y2)
+ {
+ this();
+ this.point[0] = new PGpoint(x1, y1);
+ this.point[1] = new PGpoint(x2, y2);
+ }
+
+ /**
+ * @param p1 first point
+ * @param p2 second point
+ */
+ public PGbox(PGpoint p1, PGpoint p2)
+ {
+ this();
+ this.point[0] = p1;
+ this.point[1] = p2;
+ }
+
+ /**
+ * @param s Box definition in PostgreSQL syntax
+ * @exception SQLException if definition is invalid
+ */
+ public PGbox(String s) throws SQLException
+ {
+ this();
+ setValue(s);
+ }
+
+ /**
+ * Required constructor
+ */
+ public PGbox()
+ {
+ setType("box");
+ }
+
+ /**
+ * This method sets the value of this object. It should be overidden,
+ * but still called by subclasses.
+ *
+ * @param value a string representation of the value of the object
+ * @exception SQLException thrown if value is invalid for this type
+ */
+ public void setValue(String value) throws SQLException
+ {
+ PGtokenizer t = new PGtokenizer(value, ',');
+ if (t.getSize() != 2)
+ throw new PSQLException("postgresql.geo.box", value);
+
+ point[0] = new PGpoint(t.getToken(0));
+ point[1] = new PGpoint(t.getToken(1));
+ }
+
+ /**
+ * @param obj Object to compare with
+ * @return true if the two boxes are identical
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof PGbox)
+ {
+ PGbox p = (PGbox)obj;
+ return (p.point[0].equals(point[0]) && p.point[1].equals(point[1])) ||
+ (p.point[0].equals(point[1]) && p.point[1].equals(point[0]));
+ }
+ return false;
+ }
+
+ /**
+ * This must be overidden to allow the object to be cloned
+ */
+ public Object clone()
+ {
+ return new PGbox((PGpoint)point[0].clone(), (PGpoint)point[1].clone());
+ }
+
+ /**
+ * @return the PGbox in the syntax expected by org.postgresql
+ */
+ public String getValue()
+ {
+ return point[0].toString() + "," + point[1].toString();
+ }
}
diff --git a/src/interfaces/jdbc/org/postgresql/geometric/PGcircle.java b/src/interfaces/jdbc/org/postgresql/geometric/PGcircle.java
index 9a1333e4e8c..b716fa75a82 100644
--- a/src/interfaces/jdbc/org/postgresql/geometric/PGcircle.java
+++ b/src/interfaces/jdbc/org/postgresql/geometric/PGcircle.java
@@ -8,101 +8,105 @@ import org.postgresql.util.*;
* This represents org.postgresql's circle datatype, consisting of a point and
* a radius
*/
-public class PGcircle extends PGobject implements Serializable,Cloneable
+public class PGcircle extends PGobject implements Serializable, Cloneable
{
- /**
- * This is the centre point
- */
- public PGpoint center;
-
- /**
- * This is the radius
- */
- double radius;
-
- /**
- * @param x coordinate of centre
- * @param y coordinate of centre
- * @param r radius of circle
- */
- public PGcircle(double x,double y,double r)
- {
- this(new PGpoint(x,y),r);
- }
-
- /**
- * @param c PGpoint describing the circle's centre
- * @param r radius of circle
- */
- public PGcircle(PGpoint c,double r)
- {
- this();
- this.center = c;
- this.radius = r;
- }
-
- /**
- * @param s definition of the circle in PostgreSQL's syntax.
- * @exception SQLException on conversion failure
- */
- public PGcircle(String s) throws SQLException
- {
- this();
- setValue(s);
- }
-
- /**
- * This constructor is used by the driver.
- */
- public PGcircle()
- {
- setType("circle");
- }
-
- /**
- * @param s definition of the circle in PostgreSQL's syntax.
- * @exception SQLException on conversion failure
- */
- public void setValue(String s) throws SQLException
- {
- PGtokenizer t = new PGtokenizer(PGtokenizer.removeAngle(s),',');
- if(t.getSize() != 2)
- throw new PSQLException("postgresql.geo.circle",s);
-
- try {
- center = new PGpoint(t.getToken(0));
- radius = Double.valueOf(t.getToken(1)).doubleValue();
- } catch(NumberFormatException e) {
- throw new PSQLException("postgresql.geo.circle",e);
- }
- }
-
- /**
- * @param obj Object to compare with
- * @return true if the two boxes are identical
- */
- public boolean equals(Object obj)
- {
- if(obj instanceof PGcircle) {
- PGcircle p = (PGcircle)obj;
- return p.center.equals(center) && p.radius==radius;
- }
- return false;
- }
-
- /**
- * This must be overidden to allow the object to be cloned
- */
- public Object clone()
- {
- return new PGcircle((PGpoint)center.clone(),radius);
- }
-
- /**
- * @return the PGcircle in the syntax expected by org.postgresql
- */
- public String getValue()
- {
- return "<"+center+","+radius+">";
- }
+ /**
+ * This is the centre point
+ */
+ public PGpoint center;
+
+ /**
+ * This is the radius
+ */
+ double radius;
+
+ /**
+ * @param x coordinate of centre
+ * @param y coordinate of centre
+ * @param r radius of circle
+ */
+ public PGcircle(double x, double y, double r)
+ {
+ this(new PGpoint(x, y), r);
+ }
+
+ /**
+ * @param c PGpoint describing the circle's centre
+ * @param r radius of circle
+ */
+ public PGcircle(PGpoint c, double r)
+ {
+ this();
+ this.center = c;
+ this.radius = r;
+ }
+
+ /**
+ * @param s definition of the circle in PostgreSQL's syntax.
+ * @exception SQLException on conversion failure
+ */
+ public PGcircle(String s) throws SQLException
+ {
+ this();
+ setValue(s);
+ }
+
+ /**
+ * This constructor is used by the driver.
+ */
+ public PGcircle()
+ {
+ setType("circle");
+ }
+
+ /**
+ * @param s definition of the circle in PostgreSQL's syntax.
+ * @exception SQLException on conversion failure
+ */
+ public void setValue(String s) throws SQLException
+ {
+ PGtokenizer t = new PGtokenizer(PGtokenizer.removeAngle(s), ',');
+ if (t.getSize() != 2)
+ throw new PSQLException("postgresql.geo.circle", s);
+
+ try
+ {
+ center = new PGpoint(t.getToken(0));
+ radius = Double.valueOf(t.getToken(1)).doubleValue();
+ }
+ catch (NumberFormatException e)
+ {
+ throw new PSQLException("postgresql.geo.circle", e);
+ }
+ }
+
+ /**
+ * @param obj Object to compare with
+ * @return true if the two boxes are identical
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof PGcircle)
+ {
+ PGcircle p = (PGcircle)obj;
+ return p.center.equals(center) && p.radius == radius;
+ }
+ return false;
+ }
+
+ /**
+ * This must be overidden to allow the object to be cloned
+ */
+ public Object clone()
+ {
+ return new PGcircle((PGpoint)center.clone(), radius);
+ }
+
+ /**
+ * @return the PGcircle in the syntax expected by org.postgresql
+ */
+ public String getValue()
+ {
+ return "<" + center + "," + radius + ">";
+ }
}
diff --git a/src/interfaces/jdbc/org/postgresql/geometric/PGline.java b/src/interfaces/jdbc/org/postgresql/geometric/PGline.java
index 4901b6f2f16..cc2b05ecb1d 100644
--- a/src/interfaces/jdbc/org/postgresql/geometric/PGline.java
+++ b/src/interfaces/jdbc/org/postgresql/geometric/PGline.java
@@ -10,94 +10,95 @@ import org.postgresql.util.*;
* Currently line is not yet implemented in the backend, but this class
* ensures that when it's done were ready for it.
*/
-public class PGline extends PGobject implements Serializable,Cloneable
+public class PGline extends PGobject implements Serializable, Cloneable
{
- /**
- * These are the two points.
- */
- public PGpoint point[] = new PGpoint[2];
-
- /**
- * @param x1 coordinate for first point
- * @param y1 coordinate for first point
- * @param x2 coordinate for second point
- * @param y2 coordinate for second point
- */
- public PGline(double x1,double y1,double x2,double y2)
- {
- this(new PGpoint(x1,y1),new PGpoint(x2,y2));
- }
-
- /**
- * @param p1 first point
- * @param p2 second point
- */
- public PGline(PGpoint p1,PGpoint p2)
- {
- this();
- this.point[0] = p1;
- this.point[1] = p2;
- }
-
- /**
- * @param s definition of the circle in PostgreSQL's syntax.
- * @exception SQLException on conversion failure
- */
- public PGline(String s) throws SQLException
- {
- this();
- setValue(s);
- }
-
- /**
- * reuired by the driver
- */
- public PGline()
- {
- setType("line");
- }
-
- /**
- * @param s Definition of the line segment in PostgreSQL's syntax
- * @exception SQLException on conversion failure
- */
- public void setValue(String s) throws SQLException
- {
- PGtokenizer t = new PGtokenizer(PGtokenizer.removeBox(s),',');
- if(t.getSize() != 2)
- throw new PSQLException("postgresql.geo.line",s);
-
- point[0] = new PGpoint(t.getToken(0));
- point[1] = new PGpoint(t.getToken(1));
- }
-
- /**
- * @param obj Object to compare with
- * @return true if the two boxes are identical
- */
- public boolean equals(Object obj)
- {
- if(obj instanceof PGline) {
- PGline p = (PGline)obj;
- return (p.point[0].equals(point[0]) && p.point[1].equals(point[1])) ||
- (p.point[0].equals(point[1]) && p.point[1].equals(point[0]));
- }
- return false;
- }
-
- /**
- * This must be overidden to allow the object to be cloned
- */
- public Object clone()
- {
- return new PGline((PGpoint)point[0].clone(),(PGpoint)point[1].clone());
- }
-
- /**
- * @return the PGline in the syntax expected by org.postgresql
- */
- public String getValue()
- {
- return "["+point[0]+","+point[1]+"]";
- }
+ /**
+ * These are the two points.
+ */
+ public PGpoint point[] = new PGpoint[2];
+
+ /**
+ * @param x1 coordinate for first point
+ * @param y1 coordinate for first point
+ * @param x2 coordinate for second point
+ * @param y2 coordinate for second point
+ */
+ public PGline(double x1, double y1, double x2, double y2)
+ {
+ this(new PGpoint(x1, y1), new PGpoint(x2, y2));
+ }
+
+ /**
+ * @param p1 first point
+ * @param p2 second point
+ */
+ public PGline(PGpoint p1, PGpoint p2)
+ {
+ this();
+ this.point[0] = p1;
+ this.point[1] = p2;
+ }
+
+ /**
+ * @param s definition of the circle in PostgreSQL's syntax.
+ * @exception SQLException on conversion failure
+ */
+ public PGline(String s) throws SQLException
+ {
+ this();
+ setValue(s);
+ }
+
+ /**
+ * reuired by the driver
+ */
+ public PGline()
+ {
+ setType("line");
+ }
+
+ /**
+ * @param s Definition of the line segment in PostgreSQL's syntax
+ * @exception SQLException on conversion failure
+ */
+ public void setValue(String s) throws SQLException
+ {
+ PGtokenizer t = new PGtokenizer(PGtokenizer.removeBox(s), ',');
+ if (t.getSize() != 2)
+ throw new PSQLException("postgresql.geo.line", s);
+
+ point[0] = new PGpoint(t.getToken(0));
+ point[1] = new PGpoint(t.getToken(1));
+ }
+
+ /**
+ * @param obj Object to compare with
+ * @return true if the two boxes are identical
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof PGline)
+ {
+ PGline p = (PGline)obj;
+ return (p.point[0].equals(point[0]) && p.point[1].equals(point[1])) ||
+ (p.point[0].equals(point[1]) && p.point[1].equals(point[0]));
+ }
+ return false;
+ }
+
+ /**
+ * This must be overidden to allow the object to be cloned
+ */
+ public Object clone()
+ {
+ return new PGline((PGpoint)point[0].clone(), (PGpoint)point[1].clone());
+ }
+
+ /**
+ * @return the PGline in the syntax expected by org.postgresql
+ */
+ public String getValue()
+ {
+ return "[" + point[0] + "," + point[1] + "]";
+ }
}
diff --git a/src/interfaces/jdbc/org/postgresql/geometric/PGlseg.java b/src/interfaces/jdbc/org/postgresql/geometric/PGlseg.java
index ec0986963bd..c63d980ffa4 100644
--- a/src/interfaces/jdbc/org/postgresql/geometric/PGlseg.java
+++ b/src/interfaces/jdbc/org/postgresql/geometric/PGlseg.java
@@ -7,94 +7,95 @@ import org.postgresql.util.*;
/**
* This implements a lseg (line segment) consisting of two points
*/
-public class PGlseg extends PGobject implements Serializable,Cloneable
+public class PGlseg extends PGobject implements Serializable, Cloneable
{
- /**
- * These are the two points.
- */
- public PGpoint point[] = new PGpoint[2];
-
- /**
- * @param x1 coordinate for first point
- * @param y1 coordinate for first point
- * @param x2 coordinate for second point
- * @param y2 coordinate for second point
- */
- public PGlseg(double x1,double y1,double x2,double y2)
- {
- this(new PGpoint(x1,y1),new PGpoint(x2,y2));
- }
-
- /**
- * @param p1 first point
- * @param p2 second point
- */
- public PGlseg(PGpoint p1,PGpoint p2)
- {
- this();
- this.point[0] = p1;
- this.point[1] = p2;
- }
-
- /**
- * @param s definition of the circle in PostgreSQL's syntax.
- * @exception SQLException on conversion failure
- */
- public PGlseg(String s) throws SQLException
- {
- this();
- setValue(s);
- }
-
- /**
- * reuired by the driver
- */
- public PGlseg()
- {
- setType("lseg");
- }
-
- /**
- * @param s Definition of the line segment in PostgreSQL's syntax
- * @exception SQLException on conversion failure
- */
- public void setValue(String s) throws SQLException
- {
- PGtokenizer t = new PGtokenizer(PGtokenizer.removeBox(s),',');
- if(t.getSize() != 2)
- throw new PSQLException("postgresql.geo.lseg");
-
- point[0] = new PGpoint(t.getToken(0));
- point[1] = new PGpoint(t.getToken(1));
- }
-
- /**
- * @param obj Object to compare with
- * @return true if the two boxes are identical
- */
- public boolean equals(Object obj)
- {
- if(obj instanceof PGlseg) {
- PGlseg p = (PGlseg)obj;
- return (p.point[0].equals(point[0]) && p.point[1].equals(point[1])) ||
- (p.point[0].equals(point[1]) && p.point[1].equals(point[0]));
- }
- return false;
- }
-
- /**
- * This must be overidden to allow the object to be cloned
- */
- public Object clone()
- {
- return new PGlseg((PGpoint)point[0].clone(),(PGpoint)point[1].clone());
- }
-
- /**
- * @return the PGlseg in the syntax expected by org.postgresql
- */
- public String getValue()
- {
- return "["+point[0]+","+point[1]+"]";
- }
+ /**
+ * These are the two points.
+ */
+ public PGpoint point[] = new PGpoint[2];
+
+ /**
+ * @param x1 coordinate for first point
+ * @param y1 coordinate for first point
+ * @param x2 coordinate for second point
+ * @param y2 coordinate for second point
+ */
+ public PGlseg(double x1, double y1, double x2, double y2)
+ {
+ this(new PGpoint(x1, y1), new PGpoint(x2, y2));
+ }
+
+ /**
+ * @param p1 first point
+ * @param p2 second point
+ */
+ public PGlseg(PGpoint p1, PGpoint p2)
+ {
+ this();
+ this.point[0] = p1;
+ this.point[1] = p2;
+ }
+
+ /**
+ * @param s definition of the circle in PostgreSQL's syntax.
+ * @exception SQLException on conversion failure
+ */
+ public PGlseg(String s) throws SQLException
+ {
+ this();
+ setValue(s);
+ }
+
+ /**
+ * reuired by the driver
+ */
+ public PGlseg()
+ {
+ setType("lseg");
+ }
+
+ /**
+ * @param s Definition of the line segment in PostgreSQL's syntax
+ * @exception SQLException on conversion failure
+ */
+ public void setValue(String s) throws SQLException
+ {
+ PGtokenizer t = new PGtokenizer(PGtokenizer.removeBox(s), ',');
+ if (t.getSize() != 2)
+ throw new PSQLException("postgresql.geo.lseg");
+
+ point[0] = new PGpoint(t.getToken(0));
+ point[1] = new PGpoint(t.getToken(1));
+ }
+
+ /**
+ * @param obj Object to compare with
+ * @return true if the two boxes are identical
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof PGlseg)
+ {
+ PGlseg p = (PGlseg)obj;
+ return (p.point[0].equals(point[0]) && p.point[1].equals(point[1])) ||
+ (p.point[0].equals(point[1]) && p.point[1].equals(point[0]));
+ }
+ return false;
+ }
+
+ /**
+ * This must be overidden to allow the object to be cloned
+ */
+ public Object clone()
+ {
+ return new PGlseg((PGpoint)point[0].clone(), (PGpoint)point[1].clone());
+ }
+
+ /**
+ * @return the PGlseg in the syntax expected by org.postgresql
+ */
+ public String getValue()
+ {
+ return "[" + point[0] + "," + point[1] + "]";
+ }
}
diff --git a/src/interfaces/jdbc/org/postgresql/geometric/PGpath.java b/src/interfaces/jdbc/org/postgresql/geometric/PGpath.java
index 2e5b4674fbb..47ebfd82e3b 100644
--- a/src/interfaces/jdbc/org/postgresql/geometric/PGpath.java
+++ b/src/interfaces/jdbc/org/postgresql/geometric/PGpath.java
@@ -7,139 +7,146 @@ import org.postgresql.util.*;
/**
* This implements a path (a multiple segmented line, which may be closed)
*/
-public class PGpath extends PGobject implements Serializable,Cloneable
+public class PGpath extends PGobject implements Serializable, Cloneable
{
- /**
- * True if the path is open, false if closed
- */
- public boolean open;
-
- /**
- * The points defining this path
- */
- public PGpoint points[];
-
- /**
- * @param points the PGpoints that define the path
- * @param open True if the path is open, false if closed
- */
- public PGpath(PGpoint[] points,boolean open)
- {
- this();
- this.points = points;
- this.open = open;
- }
-
- /**
- * Required by the driver
- */
- public PGpath()
- {
- setType("path");
- }
-
- /**
- * @param s definition of the circle in PostgreSQL's syntax.
- * @exception SQLException on conversion failure
- */
- public PGpath(String s) throws SQLException
- {
- this();
- setValue(s);
- }
-
- /**
- * @param s Definition of the path in PostgreSQL's syntax
- * @exception SQLException on conversion failure
- */
- public void setValue(String s) throws SQLException
- {
- // First test to see if were open
- if(s.startsWith("[") && s.endsWith("]")) {
- open = true;
- s = PGtokenizer.removeBox(s);
- } else if(s.startsWith("(") && s.endsWith(")")) {
- open = false;
- s = PGtokenizer.removePara(s);
- } else
- throw new PSQLException("postgresql.geo.path");
-
- PGtokenizer t = new PGtokenizer(s,',');
- int npoints = t.getSize();
- points = new PGpoint[npoints];
- for(int p=0;p<npoints;p++)
- points[p] = new PGpoint(t.getToken(p));
- }
-
- /**
- * @param obj Object to compare with
- * @return true if the two boxes are identical
- */
- public boolean equals(Object obj)
- {
- if(obj instanceof PGpath) {
- PGpath p = (PGpath)obj;
-
- if(p.points.length != points.length)
- return false;
-
- if(p.open != open)
- return false;
-
- for(int i=0;i<points.length;i++)
- if(!points[i].equals(p.points[i]))
- return false;
-
- return true;
- }
- return false;
- }
-
- /**
- * This must be overidden to allow the object to be cloned
- */
- public Object clone()
- {
- PGpoint ary[] = new PGpoint[points.length];
- for(int i=0;i<points.length;i++)
- ary[i]=(PGpoint)points[i].clone();
- return new PGpath(ary,open);
- }
-
- /**
- * This returns the polygon in the syntax expected by org.postgresql
- */
- public String getValue()
- {
- StringBuffer b = new StringBuffer(open?"[":"(");
-
- for(int p=0;p<points.length;p++) {
- if(p>0) b.append(",");
- b.append(points[p].toString());
- }
- b.append(open?"]":")");
-
- return b.toString();
- }
-
- public boolean isOpen()
- {
- return open;
- }
-
- public boolean isClosed()
- {
- return !open;
- }
-
- public void closePath()
- {
- open = false;
- }
-
- public void openPath()
- {
- open = true;
- }
-
+ /**
+ * True if the path is open, false if closed
+ */
+ public boolean open;
+
+ /**
+ * The points defining this path
+ */
+ public PGpoint points[];
+
+ /**
+ * @param points the PGpoints that define the path
+ * @param open True if the path is open, false if closed
+ */
+ public PGpath(PGpoint[] points, boolean open)
+ {
+ this();
+ this.points = points;
+ this.open = open;
+ }
+
+ /**
+ * Required by the driver
+ */
+ public PGpath()
+ {
+ setType("path");
+ }
+
+ /**
+ * @param s definition of the circle in PostgreSQL's syntax.
+ * @exception SQLException on conversion failure
+ */
+ public PGpath(String s) throws SQLException
+ {
+ this();
+ setValue(s);
+ }
+
+ /**
+ * @param s Definition of the path in PostgreSQL's syntax
+ * @exception SQLException on conversion failure
+ */
+ public void setValue(String s) throws SQLException
+ {
+ // First test to see if were open
+ if (s.startsWith("[") && s.endsWith("]"))
+ {
+ open = true;
+ s = PGtokenizer.removeBox(s);
+ }
+ else if (s.startsWith("(") && s.endsWith(")"))
+ {
+ open = false;
+ s = PGtokenizer.removePara(s);
+ }
+ else
+ throw new PSQLException("postgresql.geo.path");
+
+ PGtokenizer t = new PGtokenizer(s, ',');
+ int npoints = t.getSize();
+ points = new PGpoint[npoints];
+ for (int p = 0;p < npoints;p++)
+ points[p] = new PGpoint(t.getToken(p));
+ }
+
+ /**
+ * @param obj Object to compare with
+ * @return true if the two boxes are identical
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof PGpath)
+ {
+ PGpath p = (PGpath)obj;
+
+ if (p.points.length != points.length)
+ return false;
+
+ if (p.open != open)
+ return false;
+
+ for (int i = 0;i < points.length;i++)
+ if (!points[i].equals(p.points[i]))
+ return false;
+
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * This must be overidden to allow the object to be cloned
+ */
+ public Object clone()
+ {
+ PGpoint ary[] = new PGpoint[points.length];
+ for (int i = 0;i < points.length;i++)
+ ary[i] = (PGpoint)points[i].clone();
+ return new PGpath(ary, open);
+ }
+
+ /**
+ * This returns the polygon in the syntax expected by org.postgresql
+ */
+ public String getValue()
+ {
+ StringBuffer b = new StringBuffer(open ? "[" : "(");
+
+ for (int p = 0;p < points.length;p++)
+ {
+ if (p > 0)
+ b.append(",");
+ b.append(points[p].toString());
+ }
+ b.append(open ? "]" : ")");
+
+ return b.toString();
+ }
+
+ public boolean isOpen()
+ {
+ return open;
+ }
+
+ public boolean isClosed()
+ {
+ return !open;
+ }
+
+ public void closePath()
+ {
+ open = false;
+ }
+
+ public void openPath()
+ {
+ open = true;
+ }
+
}
diff --git a/src/interfaces/jdbc/org/postgresql/geometric/PGpoint.java b/src/interfaces/jdbc/org/postgresql/geometric/PGpoint.java
index eeb71b2773d..455e42aff43 100644
--- a/src/interfaces/jdbc/org/postgresql/geometric/PGpoint.java
+++ b/src/interfaces/jdbc/org/postgresql/geometric/PGpoint.java
@@ -12,156 +12,160 @@ import org.postgresql.util.*;
*
* <p>It maps to the point datatype in org.postgresql.
*/
-public class PGpoint extends PGobject implements Serializable,Cloneable
+public class PGpoint extends PGobject implements Serializable, Cloneable
{
- /**
- * The X coordinate of the point
- */
- public double x;
-
- /**
- * The Y coordinate of the point
- */
- public double y;
-
- /**
- * @param x coordinate
- * @param y coordinate
- */
- public PGpoint(double x,double y)
- {
- this();
- this.x = x;
- this.y = y;
- }
-
- /**
- * This is called mainly from the other geometric types, when a
- * point is imbeded within their definition.
- *
- * @param value Definition of this point in PostgreSQL's syntax
- */
- public PGpoint(String value) throws SQLException
- {
- this();
- setValue(value);
- }
-
- /**
- * Required by the driver
- */
- public PGpoint()
- {
- setType("point");
- }
-
- /**
- * @param s Definition of this point in PostgreSQL's syntax
- * @exception SQLException on conversion failure
- */
- public void setValue(String s) throws SQLException
- {
- PGtokenizer t = new PGtokenizer(PGtokenizer.removePara(s),',');
- try {
- x = Double.valueOf(t.getToken(0)).doubleValue();
- y = Double.valueOf(t.getToken(1)).doubleValue();
- } catch(NumberFormatException e) {
- throw new PSQLException("postgresql.geo.point",e.toString());
- }
- }
-
- /**
- * @param obj Object to compare with
- * @return true if the two boxes are identical
- */
- public boolean equals(Object obj)
- {
- if(obj instanceof PGpoint) {
- PGpoint p = (PGpoint)obj;
- return x == p.x && y == p.y;
- }
- return false;
- }
-
- /**
- * This must be overidden to allow the object to be cloned
- */
- public Object clone()
- {
- return new PGpoint(x,y);
- }
-
- /**
- * @return the PGpoint in the syntax expected by org.postgresql
- */
- public String getValue()
- {
- return "("+x+","+y+")";
- }
-
- /**
- * Translate the point with the supplied amount.
- * @param x integer amount to add on the x axis
- * @param y integer amount to add on the y axis
- */
- public void translate(int x,int y)
- {
- translate((double)x,(double)y);
- }
-
- /**
- * Translate the point with the supplied amount.
- * @param x double amount to add on the x axis
- * @param y double amount to add on the y axis
- */
- public void translate(double x,double y)
- {
- this.x += x;
- this.y += y;
- }
-
- /**
- * Moves the point to the supplied coordinates.
- * @param x integer coordinate
- * @param y integer coordinate
- */
- public void move(int x,int y)
- {
- setLocation(x,y);
- }
-
- /**
- * Moves the point to the supplied coordinates.
- * @param x double coordinate
- * @param y double coordinate
- */
- public void move(double x,double y)
- {
- this.x = x;
- this.y = y;
- }
-
- /**
- * Moves the point to the supplied coordinates.
- * refer to java.awt.Point for description of this
- * @param x integer coordinate
- * @param y integer coordinate
- * @see java.awt.Point
- */
- public void setLocation(int x,int y)
- {
- move((double)x,(double)y);
- }
-
- /**
- * Moves the point to the supplied java.awt.Point
- * refer to java.awt.Point for description of this
- * @param p Point to move to
- * @see java.awt.Point
- */
- public void setLocation(Point p)
- {
- setLocation(p.x,p.y);
- }
-
+ /**
+ * The X coordinate of the point
+ */
+ public double x;
+
+ /**
+ * The Y coordinate of the point
+ */
+ public double y;
+
+ /**
+ * @param x coordinate
+ * @param y coordinate
+ */
+ public PGpoint(double x, double y)
+ {
+ this();
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * This is called mainly from the other geometric types, when a
+ * point is imbeded within their definition.
+ *
+ * @param value Definition of this point in PostgreSQL's syntax
+ */
+ public PGpoint(String value) throws SQLException
+ {
+ this();
+ setValue(value);
+ }
+
+ /**
+ * Required by the driver
+ */
+ public PGpoint()
+ {
+ setType("point");
+ }
+
+ /**
+ * @param s Definition of this point in PostgreSQL's syntax
+ * @exception SQLException on conversion failure
+ */
+ public void setValue(String s) throws SQLException
+ {
+ PGtokenizer t = new PGtokenizer(PGtokenizer.removePara(s), ',');
+ try
+ {
+ x = Double.valueOf(t.getToken(0)).doubleValue();
+ y = Double.valueOf(t.getToken(1)).doubleValue();
+ }
+ catch (NumberFormatException e)
+ {
+ throw new PSQLException("postgresql.geo.point", e.toString());
+ }
+ }
+
+ /**
+ * @param obj Object to compare with
+ * @return true if the two boxes are identical
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof PGpoint)
+ {
+ PGpoint p = (PGpoint)obj;
+ return x == p.x && y == p.y;
+ }
+ return false;
+ }
+
+ /**
+ * This must be overidden to allow the object to be cloned
+ */
+ public Object clone()
+ {
+ return new PGpoint(x, y);
+ }
+
+ /**
+ * @return the PGpoint in the syntax expected by org.postgresql
+ */
+ public String getValue()
+ {
+ return "(" + x + "," + y + ")";
+ }
+
+ /**
+ * Translate the point with the supplied amount.
+ * @param x integer amount to add on the x axis
+ * @param y integer amount to add on the y axis
+ */
+ public void translate(int x, int y)
+ {
+ translate((double)x, (double)y);
+ }
+
+ /**
+ * Translate the point with the supplied amount.
+ * @param x double amount to add on the x axis
+ * @param y double amount to add on the y axis
+ */
+ public void translate(double x, double y)
+ {
+ this.x += x;
+ this.y += y;
+ }
+
+ /**
+ * Moves the point to the supplied coordinates.
+ * @param x integer coordinate
+ * @param y integer coordinate
+ */
+ public void move(int x, int y)
+ {
+ setLocation(x, y);
+ }
+
+ /**
+ * Moves the point to the supplied coordinates.
+ * @param x double coordinate
+ * @param y double coordinate
+ */
+ public void move(double x, double y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Moves the point to the supplied coordinates.
+ * refer to java.awt.Point for description of this
+ * @param x integer coordinate
+ * @param y integer coordinate
+ * @see java.awt.Point
+ */
+ public void setLocation(int x, int y)
+ {
+ move((double)x, (double)y);
+ }
+
+ /**
+ * Moves the point to the supplied java.awt.Point
+ * refer to java.awt.Point for description of this
+ * @param p Point to move to
+ * @see java.awt.Point
+ */
+ public void setLocation(Point p)
+ {
+ setLocation(p.x, p.y);
+ }
+
}
diff --git a/src/interfaces/jdbc/org/postgresql/geometric/PGpolygon.java b/src/interfaces/jdbc/org/postgresql/geometric/PGpolygon.java
index b805a1df308..12c45fd709f 100644
--- a/src/interfaces/jdbc/org/postgresql/geometric/PGpolygon.java
+++ b/src/interfaces/jdbc/org/postgresql/geometric/PGpolygon.java
@@ -7,99 +7,102 @@ import org.postgresql.util.*;
/**
* This implements the polygon datatype within PostgreSQL.
*/
-public class PGpolygon extends PGobject implements Serializable,Cloneable
+public class PGpolygon extends PGobject implements Serializable, Cloneable
{
- /**
- * The points defining the polygon
- */
- public PGpoint points[];
-
- /**
- * Creates a polygon using an array of PGpoints
- *
- * @param points the points defining the polygon
- */
- public PGpolygon(PGpoint[] points)
- {
- this();
- this.points = points;
- }
-
- /**
- * @param s definition of the circle in PostgreSQL's syntax.
- * @exception SQLException on conversion failure
- */
- public PGpolygon(String s) throws SQLException
- {
- this();
- setValue(s);
- }
-
- /**
- * Required by the driver
- */
- public PGpolygon()
- {
- setType("polygon");
- }
-
- /**
- * @param s Definition of the polygon in PostgreSQL's syntax
- * @exception SQLException on conversion failure
- */
- public void setValue(String s) throws SQLException
- {
- PGtokenizer t = new PGtokenizer(PGtokenizer.removePara(s),',');
- int npoints = t.getSize();
- points = new PGpoint[npoints];
- for(int p=0;p<npoints;p++)
- points[p] = new PGpoint(t.getToken(p));
- }
-
- /**
- * @param obj Object to compare with
- * @return true if the two boxes are identical
- */
- public boolean equals(Object obj)
- {
- if(obj instanceof PGpolygon) {
- PGpolygon p = (PGpolygon)obj;
-
- if(p.points.length != points.length)
- return false;
-
- for(int i=0;i<points.length;i++)
- if(!points[i].equals(p.points[i]))
- return false;
-
- return true;
- }
- return false;
- }
-
- /**
- * This must be overidden to allow the object to be cloned
- */
- public Object clone()
- {
- PGpoint ary[] = new PGpoint[points.length];
- for(int i=0;i<points.length;i++)
- ary[i] = (PGpoint)points[i].clone();
- return new PGpolygon(ary);
- }
-
- /**
- * @return the PGpolygon in the syntax expected by org.postgresql
- */
- public String getValue()
- {
- StringBuffer b = new StringBuffer();
- b.append("(");
- for(int p=0;p<points.length;p++) {
- if(p>0) b.append(",");
- b.append(points[p].toString());
- }
- b.append(")");
- return b.toString();
- }
+ /**
+ * The points defining the polygon
+ */
+ public PGpoint points[];
+
+ /**
+ * Creates a polygon using an array of PGpoints
+ *
+ * @param points the points defining the polygon
+ */
+ public PGpolygon(PGpoint[] points)
+ {
+ this();
+ this.points = points;
+ }
+
+ /**
+ * @param s definition of the circle in PostgreSQL's syntax.
+ * @exception SQLException on conversion failure
+ */
+ public PGpolygon(String s) throws SQLException
+ {
+ this();
+ setValue(s);
+ }
+
+ /**
+ * Required by the driver
+ */
+ public PGpolygon()
+ {
+ setType("polygon");
+ }
+
+ /**
+ * @param s Definition of the polygon in PostgreSQL's syntax
+ * @exception SQLException on conversion failure
+ */
+ public void setValue(String s) throws SQLException
+ {
+ PGtokenizer t = new PGtokenizer(PGtokenizer.removePara(s), ',');
+ int npoints = t.getSize();
+ points = new PGpoint[npoints];
+ for (int p = 0;p < npoints;p++)
+ points[p] = new PGpoint(t.getToken(p));
+ }
+
+ /**
+ * @param obj Object to compare with
+ * @return true if the two boxes are identical
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof PGpolygon)
+ {
+ PGpolygon p = (PGpolygon)obj;
+
+ if (p.points.length != points.length)
+ return false;
+
+ for (int i = 0;i < points.length;i++)
+ if (!points[i].equals(p.points[i]))
+ return false;
+
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * This must be overidden to allow the object to be cloned
+ */
+ public Object clone()
+ {
+ PGpoint ary[] = new PGpoint[points.length];
+ for (int i = 0;i < points.length;i++)
+ ary[i] = (PGpoint)points[i].clone();
+ return new PGpolygon(ary);
+ }
+
+ /**
+ * @return the PGpolygon in the syntax expected by org.postgresql
+ */
+ public String getValue()
+ {
+ StringBuffer b = new StringBuffer();
+ b.append("(");
+ for (int p = 0;p < points.length;p++)
+ {
+ if (p > 0)
+ b.append(",");
+ b.append(points[p].toString());
+ }
+ b.append(")");
+ return b.toString();
+ }
}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/CallableStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/CallableStatement.java
index be527668359..2947dfe82d0 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/CallableStatement.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/CallableStatement.java
@@ -19,8 +19,8 @@ import java.math.*;
* Parameters are refered to sequentially, by number. The first parameter
* is 1.
*
- * {?= call <procedure-name>[<arg1>,<arg2>, ...]}
- * {call <procedure-name>[<arg1>,<arg2>, ...]}
+ * {?= call <procedure-name>[<arg1>,<arg2>, ...]}
+ * {call <procedure-name>[<arg1>,<arg2>, ...]}
*
*
* <p>IN parameter values are set using the set methods inherited from
@@ -33,7 +33,7 @@ import java.math.*;
* Statement.
*
* <p>For maximum portability, a call's ResultSets and update counts should
- * be processed prior to getting the values of output parameters.
+ * be processed prior to getting the values of output parameters.
*
* @see Connection#prepareCall
* @see ResultSet
@@ -41,268 +41,282 @@ import java.math.*;
public class CallableStatement extends PreparedStatement implements java.sql.CallableStatement
{
- /**
- * @exception SQLException on failure
- */
- CallableStatement(Connection c,String q) throws SQLException
- {
- super(c,q);
- }
-
- /**
- * Before executing a stored procedure call you must explicitly
- * call registerOutParameter to register the java.sql.Type of each
- * out parameter.
- *
- * <p>Note: When reading the value of an out parameter, you must use
- * the getXXX method whose Java type XXX corresponds to the
- * parameter's registered SQL type.
- *
- * @param parameterIndex the first parameter is 1, the second is 2,...
- * @param sqlType SQL type code defined by java.sql.Types; for
- * parameters of type Numeric or Decimal use the version of
- * registerOutParameter that accepts a scale value
- * @exception SQLException if a database-access error occurs.
- */
- public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException {
- }
-
- /**
- * You must also specify the scale for numeric/decimal types:
- *
- * <p>Note: When reading the value of an out parameter, you must use
- * the getXXX method whose Java type XXX corresponds to the
- * parameter's registered SQL type.
- *
- * @param parameterIndex the first parameter is 1, the second is 2,...
- * @param sqlType use either java.sql.Type.NUMERIC or java.sql.Type.DECIMAL
- * @param scale a value greater than or equal to zero representing the
- * desired number of digits to the right of the decimal point
- * @exception SQLException if a database-access error occurs.
- */
- public void registerOutParameter(int parameterIndex, int sqlType,
- int scale) throws SQLException
- {
- }
-
- // Old api?
- //public boolean isNull(int parameterIndex) throws SQLException {
- //return true;
- //}
-
- /**
- * An OUT parameter may have the value of SQL NULL; wasNull
- * reports whether the last value read has this special value.
- *
- * <p>Note: You must first call getXXX on a parameter to read its
- * value and then call wasNull() to see if the value was SQL NULL.
- * @return true if the last parameter read was SQL NULL
- * @exception SQLException if a database-access error occurs.
- */
- public boolean wasNull() throws SQLException {
- // check to see if the last access threw an exception
- return false; // fake it for now
- }
-
- // Old api?
- //public String getChar(int parameterIndex) throws SQLException {
- //return null;
- //}
-
- /**
- * Get the value of a CHAR, VARCHAR, or LONGVARCHAR parameter as a
- * Java String.
- *
- * @param parameterIndex the first parameter is 1, the second is 2,...
- * @return the parameter value; if the value is SQL NULL, the result is null
- * @exception SQLException if a database-access error occurs.
- */
- public String getString(int parameterIndex) throws SQLException {
- return null;
- }
- //public String getVarChar(int parameterIndex) throws SQLException {
- // return null;
- //}
-
- //public String getLongVarChar(int parameterIndex) throws SQLException {
- //return null;
- //}
-
- /**
- * Get the value of a BIT parameter as a Java boolean.
- *
- * @param parameterIndex the first parameter is 1, the second is 2,...
- * @return the parameter value; if the value is SQL NULL, the result is false
- * @exception SQLException if a database-access error occurs.
- */
- public boolean getBoolean(int parameterIndex) throws SQLException {
- return false;
- }
-
- /**
- * Get the value of a TINYINT parameter as a Java byte.
- *
- * @param parameterIndex the first parameter is 1, the second is 2,...
- * @return the parameter value; if the value is SQL NULL, the result is 0
- * @exception SQLException if a database-access error occurs.
- */
- public byte getByte(int parameterIndex) throws SQLException {
- return 0;
- }
-
- /**
- * Get the value of a SMALLINT parameter as a Java short.
- *
- * @param parameterIndex the first parameter is 1, the second is 2,...
- * @return the parameter value; if the value is SQL NULL, the result is 0
- * @exception SQLException if a database-access error occurs.
- */
- public short getShort(int parameterIndex) throws SQLException {
- return 0;
- }
-
- /**
- * Get the value of an INTEGER parameter as a Java int.
- *
- * @param parameterIndex the first parameter is 1, the second is 2,...
- * @return the parameter value; if the value is SQL NULL, the result is 0
- * @exception SQLException if a database-access error occurs.
- */
-public int getInt(int parameterIndex) throws SQLException {
- return 0;
- }
-
- /**
- * Get the value of a BIGINT parameter as a Java long.
- *
- * @param parameterIndex the first parameter is 1, the second is 2,...
- * @return the parameter value; if the value is SQL NULL, the result is 0
- * @exception SQLException if a database-access error occurs.
- */
- public long getLong(int parameterIndex) throws SQLException {
- return 0;
- }
-
- /**
- * Get the value of a FLOAT parameter as a Java float.
- *
- * @param parameterIndex the first parameter is 1, the second is 2,...
- * @return the parameter value; if the value is SQL NULL, the result is 0
- * @exception SQLException if a database-access error occurs.
- */
- public float getFloat(int parameterIndex) throws SQLException {
- return (float) 0.0;
- }
-
- /**
- * Get the value of a DOUBLE parameter as a Java double.
- *
- * @param parameterIndex the first parameter is 1, the second is 2,...
- * @return the parameter value; if the value is SQL NULL, the result is 0
- * @exception SQLException if a database-access error occurs.
- */
- public double getDouble(int parameterIndex) throws SQLException {
- return 0.0;
- }
-
- /**
- * Get the value of a NUMERIC parameter as a java.math.BigDecimal
- * object.
- *
- * @param parameterIndex the first parameter is 1, the second is 2,...
- * @param scale a value greater than or equal to zero representing the
- * desired number of digits to the right of the decimal point
- * @return the parameter value; if the value is SQL NULL, the result is null
- * @exception SQLException if a database-access error occurs.
- */
- public BigDecimal getBigDecimal(int parameterIndex, int scale)
- throws SQLException {
- return null;
- }
-
- /**
- * Get the value of a SQL BINARY or VARBINARY parameter as a Java
- * byte[]
- *
- * @param parameterIndex the first parameter is 1, the second is 2,...
- * @return the parameter value; if the value is SQL NULL, the result is null
- * @exception SQLException if a database-access error occurs.
- */
- public byte[] getBytes(int parameterIndex) throws SQLException {
- return null;
- }
-
- // New API (JPM) (getLongVarBinary)
- //public byte[] getBinaryStream(int parameterIndex) throws SQLException {
- //return null;
- //}
-
- /**
- * Get the value of a SQL DATE parameter as a java.sql.Date object
- *
- * @param parameterIndex the first parameter is 1, the second is 2,...
- * @return the parameter value; if the value is SQL NULL, the result is null
- * @exception SQLException if a database-access error occurs.
- */
- public java.sql.Date getDate(int parameterIndex) throws SQLException {
- return null;
- }
-
- /**
- * Get the value of a SQL TIME parameter as a java.sql.Time object.
- *
- * @param parameterIndex the first parameter is 1, the second is 2,...
- * @return the parameter value; if the value is SQL NULL, the result is null
- * @exception SQLException if a database-access error occurs.
- */
- public java.sql.Time getTime(int parameterIndex) throws SQLException {
- return null;
- }
-
- /**
- * Get the value of a SQL TIMESTAMP parameter as a java.sql.Timestamp object.
- *
- * @param parameterIndex the first parameter is 1, the second is 2,...
- * @return the parameter value; if the value is SQL NULL, the result is null
- * @exception SQLException if a database-access error occurs.
- */
- public java.sql.Timestamp getTimestamp(int parameterIndex)
- throws SQLException {
- return null;
- }
-
- //----------------------------------------------------------------------
- // Advanced features:
-
- // You can obtain a ParameterMetaData object to get information
- // about the parameters to this CallableStatement.
- //public DatabaseMetaData getMetaData() {
- //return null;
- //}
-
- // getObject returns a Java object for the parameter.
- // See the JDBC spec's "Dynamic Programming" chapter for details.
- /**
- * Get the value of a parameter as a Java object.
- *
- * <p>This method returns a Java object whose type coresponds to the
- * SQL type that was registered for this parameter using
- * registerOutParameter.
- *
- * <P>Note that this method may be used to read datatabase-specific,
- * abstract data types. This is done by specifying a targetSqlType
- * of java.sql.types.OTHER, which allows the driver to return a
- * database-specific Java type.
- *
- * <p>See the JDBC spec's "Dynamic Programming" chapter for details.
- *
- * @param parameterIndex the first parameter is 1, the second is 2,...
- * @return A java.lang.Object holding the OUT parameter value.
- * @exception SQLException if a database-access error occurs.
- */
- public Object getObject(int parameterIndex)
- throws SQLException {
- return null;
- }
+ /**
+ * @exception SQLException on failure
+ */
+ CallableStatement(Connection c, String q) throws SQLException
+ {
+ super(c, q);
+ }
+
+ /**
+ * Before executing a stored procedure call you must explicitly
+ * call registerOutParameter to register the java.sql.Type of each
+ * out parameter.
+ *
+ * <p>Note: When reading the value of an out parameter, you must use
+ * the getXXX method whose Java type XXX corresponds to the
+ * parameter's registered SQL type.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2,...
+ * @param sqlType SQL type code defined by java.sql.Types; for
+ * parameters of type Numeric or Decimal use the version of
+ * registerOutParameter that accepts a scale value
+ * @exception SQLException if a database-access error occurs.
+ */
+ public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException
+ {}
+
+ /**
+ * You must also specify the scale for numeric/decimal types:
+ *
+ * <p>Note: When reading the value of an out parameter, you must use
+ * the getXXX method whose Java type XXX corresponds to the
+ * parameter's registered SQL type.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2,...
+ * @param sqlType use either java.sql.Type.NUMERIC or java.sql.Type.DECIMAL
+ * @param scale a value greater than or equal to zero representing the
+ * desired number of digits to the right of the decimal point
+ * @exception SQLException if a database-access error occurs.
+ */
+ public void registerOutParameter(int parameterIndex, int sqlType,
+ int scale) throws SQLException
+ {}
+
+ // Old api?
+ //public boolean isNull(int parameterIndex) throws SQLException {
+ //return true;
+ //}
+
+ /**
+ * An OUT parameter may have the value of SQL NULL; wasNull
+ * reports whether the last value read has this special value.
+ *
+ * <p>Note: You must first call getXXX on a parameter to read its
+ * value and then call wasNull() to see if the value was SQL NULL.
+ * @return true if the last parameter read was SQL NULL
+ * @exception SQLException if a database-access error occurs.
+ */
+ public boolean wasNull() throws SQLException
+ {
+ // check to see if the last access threw an exception
+ return false; // fake it for now
+ }
+
+ // Old api?
+ //public String getChar(int parameterIndex) throws SQLException {
+ //return null;
+ //}
+
+ /**
+ * Get the value of a CHAR, VARCHAR, or LONGVARCHAR parameter as a
+ * Java String.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2,...
+ * @return the parameter value; if the value is SQL NULL, the result is null
+ * @exception SQLException if a database-access error occurs.
+ */
+ public String getString(int parameterIndex) throws SQLException
+ {
+ return null;
+ }
+ //public String getVarChar(int parameterIndex) throws SQLException {
+ // return null;
+ //}
+
+ //public String getLongVarChar(int parameterIndex) throws SQLException {
+ //return null;
+ //}
+
+ /**
+ * Get the value of a BIT parameter as a Java boolean.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2,...
+ * @return the parameter value; if the value is SQL NULL, the result is false
+ * @exception SQLException if a database-access error occurs.
+ */
+ public boolean getBoolean(int parameterIndex) throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Get the value of a TINYINT parameter as a Java byte.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2,...
+ * @return the parameter value; if the value is SQL NULL, the result is 0
+ * @exception SQLException if a database-access error occurs.
+ */
+ public byte getByte(int parameterIndex) throws SQLException
+ {
+ return 0;
+ }
+
+ /**
+ * Get the value of a SMALLINT parameter as a Java short.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2,...
+ * @return the parameter value; if the value is SQL NULL, the result is 0
+ * @exception SQLException if a database-access error occurs.
+ */
+ public short getShort(int parameterIndex) throws SQLException
+ {
+ return 0;
+ }
+
+ /**
+ * Get the value of an INTEGER parameter as a Java int.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2,...
+ * @return the parameter value; if the value is SQL NULL, the result is 0
+ * @exception SQLException if a database-access error occurs.
+ */
+ public int getInt(int parameterIndex) throws SQLException
+ {
+ return 0;
+ }
+
+ /**
+ * Get the value of a BIGINT parameter as a Java long.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2,...
+ * @return the parameter value; if the value is SQL NULL, the result is 0
+ * @exception SQLException if a database-access error occurs.
+ */
+ public long getLong(int parameterIndex) throws SQLException
+ {
+ return 0;
+ }
+
+ /**
+ * Get the value of a FLOAT parameter as a Java float.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2,...
+ * @return the parameter value; if the value is SQL NULL, the result is 0
+ * @exception SQLException if a database-access error occurs.
+ */
+ public float getFloat(int parameterIndex) throws SQLException
+ {
+ return (float) 0.0;
+ }
+
+ /**
+ * Get the value of a DOUBLE parameter as a Java double.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2,...
+ * @return the parameter value; if the value is SQL NULL, the result is 0
+ * @exception SQLException if a database-access error occurs.
+ */
+ public double getDouble(int parameterIndex) throws SQLException
+ {
+ return 0.0;
+ }
+
+ /**
+ * Get the value of a NUMERIC parameter as a java.math.BigDecimal
+ * object.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2,...
+ * @param scale a value greater than or equal to zero representing the
+ * desired number of digits to the right of the decimal point
+ * @return the parameter value; if the value is SQL NULL, the result is null
+ * @exception SQLException if a database-access error occurs.
+ */
+ public BigDecimal getBigDecimal(int parameterIndex, int scale)
+ throws SQLException
+ {
+ return null;
+ }
+
+ /**
+ * Get the value of a SQL BINARY or VARBINARY parameter as a Java
+ * byte[]
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2,...
+ * @return the parameter value; if the value is SQL NULL, the result is null
+ * @exception SQLException if a database-access error occurs.
+ */
+ public byte[] getBytes(int parameterIndex) throws SQLException
+ {
+ return null;
+ }
+
+ // New API (JPM) (getLongVarBinary)
+ //public byte[] getBinaryStream(int parameterIndex) throws SQLException {
+ //return null;
+ //}
+
+ /**
+ * Get the value of a SQL DATE parameter as a java.sql.Date object
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2,...
+ * @return the parameter value; if the value is SQL NULL, the result is null
+ * @exception SQLException if a database-access error occurs.
+ */
+ public java.sql.Date getDate(int parameterIndex) throws SQLException
+ {
+ return null;
+ }
+
+ /**
+ * Get the value of a SQL TIME parameter as a java.sql.Time object.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2,...
+ * @return the parameter value; if the value is SQL NULL, the result is null
+ * @exception SQLException if a database-access error occurs.
+ */
+ public java.sql.Time getTime(int parameterIndex) throws SQLException
+ {
+ return null;
+ }
+
+ /**
+ * Get the value of a SQL TIMESTAMP parameter as a java.sql.Timestamp object.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2,...
+ * @return the parameter value; if the value is SQL NULL, the result is null
+ * @exception SQLException if a database-access error occurs.
+ */
+ public java.sql.Timestamp getTimestamp(int parameterIndex)
+ throws SQLException
+ {
+ return null;
+ }
+
+ //----------------------------------------------------------------------
+ // Advanced features:
+
+ // You can obtain a ParameterMetaData object to get information
+ // about the parameters to this CallableStatement.
+ //public DatabaseMetaData getMetaData() {
+ //return null;
+ //}
+
+ // getObject returns a Java object for the parameter.
+ // See the JDBC spec's "Dynamic Programming" chapter for details.
+ /**
+ * Get the value of a parameter as a Java object.
+ *
+ * <p>This method returns a Java object whose type coresponds to the
+ * SQL type that was registered for this parameter using
+ * registerOutParameter.
+ *
+ * <P>Note that this method may be used to read datatabase-specific,
+ * abstract data types. This is done by specifying a targetSqlType
+ * of java.sql.types.OTHER, which allows the driver to return a
+ * database-specific Java type.
+ *
+ * <p>See the JDBC spec's "Dynamic Programming" chapter for details.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2,...
+ * @return A java.lang.Object holding the OUT parameter value.
+ * @exception SQLException if a database-access error occurs.
+ */
+ public Object getObject(int parameterIndex)
+ throws SQLException
+ {
+ return null;
+ }
}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc1/Connection.java
index dfdbb818270..e05bc5b6251 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/Connection.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/Connection.java
@@ -17,9 +17,9 @@ import org.postgresql.largeobject.*;
import org.postgresql.util.*;
/**
- * $Id: Connection.java,v 1.11 2001/10/09 20:47:35 barry Exp $
+ * $Id: Connection.java,v 1.12 2001/10/25 05:59:59 momjian Exp $
*
- * A Connection represents a session with a specific database. Within the
+ * A Connection represents a session with a specific database. Within the
* context of a Connection, SQL statements are executed and results are
* returned.
*
@@ -29,181 +29,183 @@ import org.postgresql.util.*;
* with the getMetaData method.
*
* <p><B>Note:</B> By default, the Connection automatically commits changes
- * after executing each statement. If auto-commit has been disabled, an
+ * after executing each statement. If auto-commit has been disabled, an
* explicit commit must be done or database changes will not be saved.
*
* @see java.sql.Connection
*/
public class Connection extends org.postgresql.Connection implements java.sql.Connection
{
- // This is a cache of the DatabaseMetaData instance for this connection
- protected DatabaseMetaData metadata;
-
- /**
- * SQL statements without parameters are normally executed using
- * Statement objects. If the same SQL statement is executed many
- * times, it is more efficient to use a PreparedStatement
- *
- * @return a new Statement object
- * @exception SQLException passed through from the constructor
- */
- public java.sql.Statement createStatement() throws SQLException
- {
- return new Statement(this);
- }
-
- /**
- * A SQL statement with or without IN parameters can be pre-compiled
- * and stored in a PreparedStatement object. This object can then
- * be used to efficiently execute this statement multiple times.
- *
- * <B>Note:</B> This method is optimized for handling parametric
- * SQL statements that benefit from precompilation if the drivers
- * supports precompilation. PostgreSQL does not support precompilation.
- * In this case, the statement is not sent to the database until the
- * PreparedStatement is executed. This has no direct effect on users;
- * however it does affect which method throws certain SQLExceptions
- *
- * @param sql a SQL statement that may contain one or more '?' IN
- * parameter placeholders
- * @return a new PreparedStatement object containing the pre-compiled
- * statement.
- * @exception SQLException if a database access error occurs.
- */
- public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException
- {
- return new PreparedStatement(this, sql);
- }
-
- /**
- * A SQL stored procedure call statement is handled by creating a
- * CallableStatement for it. The CallableStatement provides methods
- * for setting up its IN and OUT parameters and methods for executing
- * it.
- *
- * <B>Note:</B> This method is optimised for handling stored procedure
- * call statements. Some drivers may send the call statement to the
- * database when the prepareCall is done; others may wait until the
- * CallableStatement is executed. This has no direct effect on users;
- * however, it does affect which method throws certain SQLExceptions
- *
- * @param sql a SQL statement that may contain one or more '?' parameter
- * placeholders. Typically this statement is a JDBC function call
- * escape string.
- * @return a new CallableStatement object containing the pre-compiled
- * SQL statement
- * @exception SQLException if a database access error occurs
- */
- public java.sql.CallableStatement prepareCall(String sql) throws SQLException
- {
- throw new PSQLException("postgresql.con.call");
- // return new CallableStatement(this, sql);
- }
-
- /**
- * Tests to see if a Connection is closed
- *
- * @return the status of the connection
- * @exception SQLException (why?)
- */
- public boolean isClosed() throws SQLException
- {
- return (pg_stream == null);
- }
-
- /**
- * A connection's database is able to provide information describing
- * its tables, its supported SQL grammar, its stored procedures, the
- * capabilities of this connection, etc. This information is made
- * available through a DatabaseMetaData object.
- *
- * @return a DatabaseMetaData object for this connection
- * @exception SQLException if a database access error occurs
- */
- public java.sql.DatabaseMetaData getMetaData() throws SQLException
- {
- if(metadata==null)
- metadata = new DatabaseMetaData(this);
- return metadata;
- }
-
- /**
- * This overides the method in org.postgresql.Connection and returns a
- * ResultSet.
- */
- public java.sql.ResultSet getResultSet(org.postgresql.Connection conn,java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount,int insertOID, boolean binaryCursor) throws SQLException
- {
- // in jdbc1 stat is ignored.
- return new org.postgresql.jdbc1.ResultSet((org.postgresql.jdbc1.Connection)conn,fields,tuples,status,updateCount,insertOID,binaryCursor);
- }
-
-
- /* An implementation of the abstract method in the parent class.
- * This implemetation uses the jdbc1Types array to support the jdbc1
- * datatypes. Basically jdbc1 and jdbc2 are the same, except that
- * jdbc2 adds the Array types.
- */
- public int getSQLType(String pgTypeName)
- {
- int sqlType = Types.OTHER; // default value
- for(int i=0;i<jdbc1Types.length;i++) {
- if(pgTypeName.equals(jdbc1Types[i])) {
- sqlType=jdbc1Typei[i];
- break;
- }
- }
- return sqlType;
- }
-
- /**
- * This table holds the org.postgresql names for the types supported.
- * Any types that map to Types.OTHER (eg POINT) don't go into this table.
- * They default automatically to Types.OTHER
- *
- * Note: This must be in the same order as below.
- *
- * Tip: keep these grouped together by the Types. value
- */
- private static final String jdbc1Types[] = {
- "int2",
- "int4","oid",
- "int8",
- "cash","money",
- "numeric",
- "float4",
- "float8",
- "bpchar","char","char2","char4","char8","char16",
- "varchar","text","name","filename",
- "bytea",
- "bool",
- "date",
- "time",
- "abstime","timestamp"
- };
-
- /**
- * This table holds the JDBC type for each entry above.
- *
- * Note: This must be in the same order as above
- *
- * Tip: keep these grouped together by the Types. value
- */
- private static final int jdbc1Typei[] = {
- Types.SMALLINT,
- Types.INTEGER,Types.INTEGER,
- Types.BIGINT,
- Types.DOUBLE,Types.DOUBLE,
- Types.NUMERIC,
- Types.REAL,
- Types.DOUBLE,
- Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,
- Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,
- Types.BINARY,
- Types.BIT,
- Types.DATE,
- Types.TIME,
- Types.TIMESTAMP,Types.TIMESTAMP
- };
+ // This is a cache of the DatabaseMetaData instance for this connection
+ protected DatabaseMetaData metadata;
+
+ /**
+ * SQL statements without parameters are normally executed using
+ * Statement objects. If the same SQL statement is executed many
+ * times, it is more efficient to use a PreparedStatement
+ *
+ * @return a new Statement object
+ * @exception SQLException passed through from the constructor
+ */
+ public java.sql.Statement createStatement() throws SQLException
+ {
+ return new Statement(this);
+ }
+
+ /**
+ * A SQL statement with or without IN parameters can be pre-compiled
+ * and stored in a PreparedStatement object. This object can then
+ * be used to efficiently execute this statement multiple times.
+ *
+ * <B>Note:</B> This method is optimized for handling parametric
+ * SQL statements that benefit from precompilation if the drivers
+ * supports precompilation. PostgreSQL does not support precompilation.
+ * In this case, the statement is not sent to the database until the
+ * PreparedStatement is executed. This has no direct effect on users;
+ * however it does affect which method throws certain SQLExceptions
+ *
+ * @param sql a SQL statement that may contain one or more '?' IN
+ * parameter placeholders
+ * @return a new PreparedStatement object containing the pre-compiled
+ * statement.
+ * @exception SQLException if a database access error occurs.
+ */
+ public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException
+ {
+ return new PreparedStatement(this, sql);
+ }
+
+ /**
+ * A SQL stored procedure call statement is handled by creating a
+ * CallableStatement for it. The CallableStatement provides methods
+ * for setting up its IN and OUT parameters and methods for executing
+ * it.
+ *
+ * <B>Note:</B> This method is optimised for handling stored procedure
+ * call statements. Some drivers may send the call statement to the
+ * database when the prepareCall is done; others may wait until the
+ * CallableStatement is executed. This has no direct effect on users;
+ * however, it does affect which method throws certain SQLExceptions
+ *
+ * @param sql a SQL statement that may contain one or more '?' parameter
+ * placeholders. Typically this statement is a JDBC function call
+ * escape string.
+ * @return a new CallableStatement object containing the pre-compiled
+ * SQL statement
+ * @exception SQLException if a database access error occurs
+ */
+ public java.sql.CallableStatement prepareCall(String sql) throws SQLException
+ {
+ throw new PSQLException("postgresql.con.call");
+ // return new CallableStatement(this, sql);
+ }
+
+ /**
+ * Tests to see if a Connection is closed
+ *
+ * @return the status of the connection
+ * @exception SQLException (why?)
+ */
+ public boolean isClosed() throws SQLException
+ {
+ return (pg_stream == null);
+ }
+
+ /**
+ * A connection's database is able to provide information describing
+ * its tables, its supported SQL grammar, its stored procedures, the
+ * capabilities of this connection, etc. This information is made
+ * available through a DatabaseMetaData object.
+ *
+ * @return a DatabaseMetaData object for this connection
+ * @exception SQLException if a database access error occurs
+ */
+ public java.sql.DatabaseMetaData getMetaData() throws SQLException
+ {
+ if (metadata == null)
+ metadata = new DatabaseMetaData(this);
+ return metadata;
+ }
+
+ /**
+ * This overides the method in org.postgresql.Connection and returns a
+ * ResultSet.
+ */
+ public java.sql.ResultSet getResultSet(org.postgresql.Connection conn, java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount, int insertOID, boolean binaryCursor) throws SQLException
+ {
+ // in jdbc1 stat is ignored.
+ return new org.postgresql.jdbc1.ResultSet((org.postgresql.jdbc1.Connection)conn, fields, tuples, status, updateCount, insertOID, binaryCursor);
+ }
+
+
+ /* An implementation of the abstract method in the parent class.
+ * This implemetation uses the jdbc1Types array to support the jdbc1
+ * datatypes. Basically jdbc1 and jdbc2 are the same, except that
+ * jdbc2 adds the Array types.
+ */
+ public int getSQLType(String pgTypeName)
+ {
+ int sqlType = Types.OTHER; // default value
+ for (int i = 0;i < jdbc1Types.length;i++)
+ {
+ if (pgTypeName.equals(jdbc1Types[i]))
+ {
+ sqlType = jdbc1Typei[i];
+ break;
+ }
+ }
+ return sqlType;
+ }
+
+ /**
+ * This table holds the org.postgresql names for the types supported.
+ * Any types that map to Types.OTHER (eg POINT) don't go into this table.
+ * They default automatically to Types.OTHER
+ *
+ * Note: This must be in the same order as below.
+ *
+ * Tip: keep these grouped together by the Types. value
+ */
+ private static final String jdbc1Types[] = {
+ "int2",
+ "int4", "oid",
+ "int8",
+ "cash", "money",
+ "numeric",
+ "float4",
+ "float8",
+ "bpchar", "char", "char2", "char4", "char8", "char16",
+ "varchar", "text", "name", "filename",
+ "bytea",
+ "bool",
+ "date",
+ "time",
+ "abstime", "timestamp"
+ };
+
+ /**
+ * This table holds the JDBC type for each entry above.
+ *
+ * Note: This must be in the same order as above
+ *
+ * Tip: keep these grouped together by the Types. value
+ */
+ private static final int jdbc1Typei[] = {
+ Types.SMALLINT,
+ Types.INTEGER, Types.INTEGER,
+ Types.BIGINT,
+ Types.DOUBLE, Types.DOUBLE,
+ Types.NUMERIC,
+ Types.REAL,
+ Types.DOUBLE,
+ Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR,
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.BINARY,
+ Types.BIT,
+ Types.DATE,
+ Types.TIME,
+ Types.TIMESTAMP, Types.TIMESTAMP
+ };
}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java b/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java
index 3b24aebc0a0..1029e7adcc7 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java
@@ -13,7 +13,7 @@ import org.postgresql.util.PSQLException;
/**
* This class provides information about the database as a whole.
*
- * $Id: DatabaseMetaData.java,v 1.34 2001/10/24 04:31:48 barry Exp $
+ * $Id: DatabaseMetaData.java,v 1.35 2001/10/25 05:59:59 momjian Exp $
*
* <p>Many of the methods here return lists of information in ResultSets. You
* can use the normal ResultSet methods such as getString and getInt to
@@ -37,2729 +37,2755 @@ import org.postgresql.util.PSQLException;
*/
public class DatabaseMetaData implements java.sql.DatabaseMetaData
{
- Connection connection; // The connection association
-
- // These define various OID's. Hopefully they will stay constant.
- static final int iVarcharOid = 1043; // OID for varchar
- static final int iBoolOid = 16; // OID for bool
- static final int iInt2Oid = 21; // OID for int2
- static final int iInt4Oid = 23; // OID for int4
- static final int VARHDRSZ = 4; // length for int4
-
- public DatabaseMetaData(Connection conn)
- {
- this.connection = conn;
- }
-
- /**
- * Can all the procedures returned by getProcedures be called
- * by the current user?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean allProceduresAreCallable() throws SQLException
- {
- return true; // For now...
- }
-
- /**
- * Can all the tables returned by getTable be SELECTed by
- * the current user?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean allTablesAreSelectable() throws SQLException
- {
- return true; // For now...
- }
-
- /**
- * What is the URL for this database?
- *
- * @return the url or null if it cannott be generated
- * @exception SQLException if a database access error occurs
- */
- public String getURL() throws SQLException
- {
- return connection.getURL();
- }
-
- /**
- * What is our user name as known to the database?
- *
- * @return our database user name
- * @exception SQLException if a database access error occurs
- */
- public String getUserName() throws SQLException
- {
- return connection.getUserName();
- }
-
- /**
- * Is the database in read-only mode?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean isReadOnly() throws SQLException
- {
- return connection.isReadOnly();
- }
-
- /**
- * Are NULL values sorted high?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean nullsAreSortedHigh() throws SQLException
- {
- return connection.haveMinimumServerVersion("7.2");
- }
-
- /**
- * Are NULL values sorted low?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean nullsAreSortedLow() throws SQLException
- {
- return false;
- }
-
- /**
- * Are NULL values sorted at the start regardless of sort order?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean nullsAreSortedAtStart() throws SQLException
- {
- return false;
- }
-
- /**
- * Are NULL values sorted at the end regardless of sort order?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean nullsAreSortedAtEnd() throws SQLException
- {
- return ! connection.haveMinimumServerVersion("7.2");
- }
-
- /**
- * What is the name of this database product - we hope that it is
- * PostgreSQL, so we return that explicitly.
- *
- * @return the database product name
- * @exception SQLException if a database access error occurs
- */
- public String getDatabaseProductName() throws SQLException
- {
- return "PostgreSQL";
- }
-
- /**
- * What is the version of this database product.
- *
- * @return the database version
- * @exception SQLException if a database access error occurs
- */
- public String getDatabaseProductVersion() throws SQLException
- {
- return connection.getDBVersionNumber();
- }
-
- /**
- * What is the name of this JDBC driver? If we don't know this
- * we are doing something wrong!
- *
- * @return the JDBC driver name
- * @exception SQLException why?
- */
- public String getDriverName() throws SQLException
- {
- return "PostgreSQL Native Driver";
- }
-
- /**
- * What is the version string of this JDBC driver? Again, this is
- * static.
- *
- * @return the JDBC driver name.
- * @exception SQLException why?
- */
- public String getDriverVersion() throws SQLException
- {
- return connection.this_driver.getVersion();
- }
-
- /**
- * What is this JDBC driver's major version number?
- *
- * @return the JDBC driver major version
- */
- public int getDriverMajorVersion()
- {
- return connection.this_driver.getMajorVersion();
- }
-
- /**
- * What is this JDBC driver's minor version number?
- *
- * @return the JDBC driver minor version
- */
- public int getDriverMinorVersion()
- {
- return connection.this_driver.getMinorVersion();
- }
-
- /**
- * Does the database store tables in a local file? No - it
- * stores them in a file on the server.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean usesLocalFiles() throws SQLException
- {
- return false;
- }
-
- /**
- * Does the database use a file for each table? Well, not really,
- * since it doesnt use local files.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean usesLocalFilePerTable() throws SQLException
- {
- return false;
- }
-
- /**
- * Does the database treat mixed case unquoted SQL identifiers
- * as case sensitive and as a result store them in mixed case?
- * A JDBC-Compliant driver will always return false.
- *
- * <p>Predicament - what do they mean by "SQL identifiers" - if it
- * means the names of the tables and columns, then the answers
- * given below are correct - otherwise I don't know.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsMixedCaseIdentifiers() throws SQLException
- {
- return false;
- }
-
- /**
- * Does the database treat mixed case unquoted SQL identifiers as
- * case insensitive and store them in upper case?
- *
- * @return true if so
- */
- public boolean storesUpperCaseIdentifiers() throws SQLException
- {
- return false;
- }
-
- /**
- * Does the database treat mixed case unquoted SQL identifiers as
- * case insensitive and store them in lower case?
- *
- * @return true if so
- */
- public boolean storesLowerCaseIdentifiers() throws SQLException
- {
- return true;
- }
-
- /**
- * Does the database treat mixed case unquoted SQL identifiers as
- * case insensitive and store them in mixed case?
- *
- * @return true if so
- */
- public boolean storesMixedCaseIdentifiers() throws SQLException
- {
- return false;
- }
-
- /**
- * Does the database treat mixed case quoted SQL identifiers as
- * case sensitive and as a result store them in mixed case? A
- * JDBC compliant driver will always return true.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException
- {
- return true;
- }
-
- /**
- * Does the database treat mixed case quoted SQL identifiers as
- * case insensitive and store them in upper case?
- *
- * @return true if so
- */
- public boolean storesUpperCaseQuotedIdentifiers() throws SQLException
- {
- return false;
- }
-
- /**
- * Does the database treat mixed case quoted SQL identifiers as case
- * insensitive and store them in lower case?
- *
- * @return true if so
- */
- public boolean storesLowerCaseQuotedIdentifiers() throws SQLException
- {
- return false;
- }
-
- /**
- * Does the database treat mixed case quoted SQL identifiers as case
- * insensitive and store them in mixed case?
- *
- * @return true if so
- */
- public boolean storesMixedCaseQuotedIdentifiers() throws SQLException
- {
- return false;
- }
-
- /**
- * What is the string used to quote SQL identifiers? This returns
- * a space if identifier quoting isn't supported. A JDBC Compliant
- * driver will always use a double quote character.
- *
- * @return the quoting string
- * @exception SQLException if a database access error occurs
- */
- public String getIdentifierQuoteString() throws SQLException
- {
- return "\"";
- }
-
- /**
- * Get a comma separated list of all a database's SQL keywords that
- * are NOT also SQL92 keywords.
- *
- * <p>Within PostgreSQL, the keywords are found in
- * src/backend/parser/keywords.c
- *
- * <p>For SQL Keywords, I took the list provided at
- * <a href="http://web.dementia.org/~shadow/sql/sql3bnf.sep93.txt">
- * http://web.dementia.org/~shadow/sql/sql3bnf.sep93.txt</a>
- * which is for SQL3, not SQL-92, but it is close enough for
- * this purpose.
- *
- * @return a comma separated list of keywords we use
- * @exception SQLException if a database access error occurs
- */
- public String getSQLKeywords() throws SQLException
- {
- return "abort,acl,add,aggregate,append,archive,arch_store,backward,binary,change,cluster,copy,database,delimiters,do,extend,explain,forward,heavy,index,inherits,isnull,light,listen,load,merge,nothing,notify,notnull,oids,purge,rename,replace,retrieve,returns,rule,recipe,setof,stdin,stdout,store,vacuum,verbose,version";
- }
-
- public String getNumericFunctions() throws SQLException
- {
- // XXX-Not Implemented
- return "";
- }
-
- public String getStringFunctions() throws SQLException
- {
- // XXX-Not Implemented
- return "";
- }
-
- public String getSystemFunctions() throws SQLException
- {
- // XXX-Not Implemented
- return "";
- }
-
- public String getTimeDateFunctions() throws SQLException
- {
- // XXX-Not Implemented
- return "";
- }
-
- /**
- * This is the string that can be used to escape '_' and '%' in
- * a search string pattern style catalog search parameters
- *
- * @return the string used to escape wildcard characters
- * @exception SQLException if a database access error occurs
- */
- public String getSearchStringEscape() throws SQLException
- {
- return "\\";
- }
-
- /**
- * Get all the "extra" characters that can be used in unquoted
- * identifier names (those beyond a-zA-Z0-9 and _)
- *
- * <p>From the file src/backend/parser/scan.l, an identifier is
- * {letter}{letter_or_digit} which makes it just those listed
- * above.
- *
- * @return a string containing the extra characters
- * @exception SQLException if a database access error occurs
- */
- public String getExtraNameCharacters() throws SQLException
- {
- return "";
- }
-
- /**
- * Is "ALTER TABLE" with an add column supported?
- * Yes for PostgreSQL 6.1
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsAlterTableWithAddColumn() throws SQLException
- {
- return true;
- }
-
- /**
- * Is "ALTER TABLE" with a drop column supported?
- * Peter 10/10/2000 This was set to true, but 7.1devel doesn't support it!
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsAlterTableWithDropColumn() throws SQLException
- {
- return false;
- }
-
- /**
- * Is column aliasing supported?
- *
- * <p>If so, the SQL AS clause can be used to provide names for
- * computed columns or to provide alias names for columns as
- * required. A JDBC Compliant driver always returns true.
- *
- * <p>e.g.
- *
- * <br><pre>
- * select count(C) as C_COUNT from T group by C;
- *
- * </pre><br>
- * should return a column named as C_COUNT instead of count(C)
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsColumnAliasing() throws SQLException
- {
- return true;
- }
-
- /**
- * Are concatenations between NULL and non-NULL values NULL? A
- * JDBC Compliant driver always returns true
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean nullPlusNonNullIsNull() throws SQLException
- {
- return true;
- }
-
- public boolean supportsConvert() throws SQLException
- {
- // XXX-Not Implemented
- return false;
- }
-
- public boolean supportsConvert(int fromType, int toType) throws SQLException
- {
- // XXX-Not Implemented
- return false;
- }
-
- /**
- * Are table correlation names supported? A JDBC Compliant
- * driver always returns true.
- *
- * @return true if so; false otherwise
- * @exception SQLException - if a database access error occurs
- */
- public boolean supportsTableCorrelationNames() throws SQLException
- {
- return true;
- }
-
- /**
- * If table correlation names are supported, are they restricted to
- * be different from the names of the tables?
- *
- * @return true if so; false otherwise
- * @exception SQLException - if a database access error occurs
- */
- public boolean supportsDifferentTableCorrelationNames() throws SQLException
- {
- return false;
- }
-
- /**
- * Are expressions in "ORDER BY" lists supported?
- *
- * <br>e.g. select * from t order by a + b;
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsExpressionsInOrderBy() throws SQLException
- {
- return true;
- }
-
- /**
- * Can an "ORDER BY" clause use columns not in the SELECT?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsOrderByUnrelated() throws SQLException
- {
- return connection.haveMinimumServerVersion("6.4");
- }
-
- /**
- * Is some form of "GROUP BY" clause supported?
- * I checked it, and yes it is.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsGroupBy() throws SQLException
- {
- return true;
- }
-
- /**
- * Can a "GROUP BY" clause use columns not in the SELECT?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsGroupByUnrelated() throws SQLException
- {
- return connection.haveMinimumServerVersion("6.4");
- }
-
- /**
- * Can a "GROUP BY" clause add columns not in the SELECT provided
- * it specifies all the columns in the SELECT? Does anyone actually
- * understand what they mean here?
- *
- * (I think this is a subset of the previous function. -- petere)
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsGroupByBeyondSelect() throws SQLException
- {
- return supportsGroupByUnrelated();
- }
-
- /**
- * Is the escape character in "LIKE" clauses supported? A
- * JDBC compliant driver always returns true.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsLikeEscapeClause() throws SQLException
- {
- return connection.haveMinimumServerVersion("7.1");
- }
-
- /**
- * Are multiple ResultSets from a single execute supported?
- * Well, I implemented it, but I dont think this is possible from
- * the back ends point of view.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsMultipleResultSets() throws SQLException
- {
- return false;
- }
-
- /**
- * Can we have multiple transactions open at once (on different
- * connections?)
- * I guess we can have, since Im relying on it.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsMultipleTransactions() throws SQLException
- {
- return true;
- }
-
- /**
- * Can columns be defined as non-nullable. A JDBC Compliant driver
- * always returns true.
- *
- * <p>This changed from false to true in v6.2 of the driver, as this
- * support was added to the backend.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsNonNullableColumns() throws SQLException
- {
- return true;
- }
-
- /**
- * Does this driver support the minimum ODBC SQL grammar. This
- * grammar is defined at:
- *
- * <p><a href="http://www.microsoft.com/msdn/sdk/platforms/doc/odbc/src/intropr.htm">http://www.microsoft.com/msdn/sdk/platforms/doc/odbc/src/intropr.htm</a>
- *
- * <p>In Appendix C. From this description, we seem to support the
- * ODBC minimal (Level 0) grammar.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsMinimumSQLGrammar() throws SQLException
- {
- return true;
- }
-
- /**
- * Does this driver support the Core ODBC SQL grammar. We need
- * SQL-92 conformance for this.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsCoreSQLGrammar() throws SQLException
- {
- return false;
- }
-
- /**
- * Does this driver support the Extended (Level 2) ODBC SQL
- * grammar. We don't conform to the Core (Level 1), so we can't
- * conform to the Extended SQL Grammar.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsExtendedSQLGrammar() throws SQLException
- {
- return false;
- }
-
- /**
- * Does this driver support the ANSI-92 entry level SQL grammar?
- * All JDBC Compliant drivers must return true. We currently
- * report false until 'schema' support is added. Then this
- * should be changed to return true, since we will be mostly
- * compliant (probably more compliant than many other databases)
- * And since this is a requirement for all JDBC drivers we
- * need to get to the point where we can return true.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsANSI92EntryLevelSQL() throws SQLException
- {
- return false;
- }
-
- /**
- * Does this driver support the ANSI-92 intermediate level SQL
- * grammar?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsANSI92IntermediateSQL() throws SQLException
- {
- return false;
- }
-
- /**
- * Does this driver support the ANSI-92 full SQL grammar?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsANSI92FullSQL() throws SQLException
- {
- return false;
- }
-
- /**
- * Is the SQL Integrity Enhancement Facility supported?
- * I haven't seen this mentioned anywhere, so I guess not
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsIntegrityEnhancementFacility() throws SQLException
- {
- return false;
- }
-
- /**
- * Is some form of outer join supported?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsOuterJoins() throws SQLException
- {
- return connection.haveMinimumServerVersion("7.1");
- }
-
- /**
- * Are full nexted outer joins supported?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsFullOuterJoins() throws SQLException
- {
- return connection.haveMinimumServerVersion("7.1");
- }
-
- /**
- * Is there limited support for outer joins?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsLimitedOuterJoins() throws SQLException
- {
- return supportsFullOuterJoins();
- }
-
- /**
- * What is the database vendor's preferred term for "schema"?
- * PostgreSQL doesn't have schemas, but when it does, we'll use the
- * term "schema".
- *
- * @return the vendor term
- * @exception SQLException if a database access error occurs
- */
- public String getSchemaTerm() throws SQLException
- {
- return "schema";
- }
-
- /**
- * What is the database vendor's preferred term for "procedure"?
- * Traditionally, "function" has been used.
- *
- * @return the vendor term
- * @exception SQLException if a database access error occurs
- */
- public String getProcedureTerm() throws SQLException
- {
- return "function";
- }
-
- /**
- * What is the database vendor's preferred term for "catalog"?
- *
- * @return the vendor term
- * @exception SQLException if a database access error occurs
- */
- public String getCatalogTerm() throws SQLException
- {
- return "database";
- }
-
- /**
- * Does a catalog appear at the start of a qualified table name?
- * (Otherwise it appears at the end).
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean isCatalogAtStart() throws SQLException
- {
- throw org.postgresql.Driver.notImplemented();
- }
-
- /**
- * What is the Catalog separator.
- *
- * @return the catalog separator string
- * @exception SQLException if a database access error occurs
- */
- public String getCatalogSeparator() throws SQLException
- {
- throw org.postgresql.Driver.notImplemented();
- }
-
- /**
- * Can a schema name be used in a data manipulation statement? Nope.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsSchemasInDataManipulation() throws SQLException
- {
- return false;
- }
-
- /**
- * Can a schema name be used in a procedure call statement? Nope.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsSchemasInProcedureCalls() throws SQLException
- {
- return false;
- }
-
- /**
- * Can a schema be used in a table definition statement? Nope.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsSchemasInTableDefinitions() throws SQLException
- {
- return false;
- }
-
- /**
- * Can a schema name be used in an index definition statement?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsSchemasInIndexDefinitions() throws SQLException
- {
- return false;
- }
-
- /**
- * Can a schema name be used in a privilege definition statement?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException
- {
- return false;
- }
-
- /**
- * Can a catalog name be used in a data manipulation statement?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsCatalogsInDataManipulation() throws SQLException
- {
- return false;
- }
-
- /**
- * Can a catalog name be used in a procedure call statement?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsCatalogsInProcedureCalls() throws SQLException
- {
- return false;
- }
-
- /**
- * Can a catalog name be used in a table definition statement?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsCatalogsInTableDefinitions() throws SQLException
- {
- return false;
- }
-
- /**
- * Can a catalog name be used in an index definition?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsCatalogsInIndexDefinitions() throws SQLException
- {
- return false;
- }
-
- /**
- * Can a catalog name be used in a privilege definition statement?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException
- {
- return false;
- }
-
- /**
- * We support cursors for gets only it seems. I dont see a method
- * to get a positioned delete.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsPositionedDelete() throws SQLException
- {
- return false; // For now...
- }
-
- /**
- * Is positioned UPDATE supported?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsPositionedUpdate() throws SQLException
- {
- return false; // For now...
- }
-
- /**
- * Is SELECT for UPDATE supported?
- *
- * @return true if so; false otherwise
- * @exception SQLException - if a database access error occurs
- */
- public boolean supportsSelectForUpdate() throws SQLException
- {
- return connection.haveMinimumServerVersion("6.5");
- }
-
- /**
- * Are stored procedure calls using the stored procedure escape
- * syntax supported?
- *
- * @return true if so; false otherwise
- * @exception SQLException - if a database access error occurs
- */
- public boolean supportsStoredProcedures() throws SQLException
- {
- return false;
- }
-
- /**
- * Are subqueries in comparison expressions supported? A JDBC
- * Compliant driver always returns true.
- *
- * @return true if so; false otherwise
- * @exception SQLException - if a database access error occurs
- */
- public boolean supportsSubqueriesInComparisons() throws SQLException
- {
- return true;
- }
-
- /**
- * Are subqueries in 'exists' expressions supported? A JDBC
- * Compliant driver always returns true.
- *
- * @return true if so; false otherwise
- * @exception SQLException - if a database access error occurs
- */
- public boolean supportsSubqueriesInExists() throws SQLException
- {
- return true;
- }
-
- /**
- * Are subqueries in 'in' statements supported? A JDBC
- * Compliant driver always returns true.
- *
- * @return true if so; false otherwise
- * @exception SQLException - if a database access error occurs
- */
- public boolean supportsSubqueriesInIns() throws SQLException
- {
- return true;
- }
-
- /**
- * Are subqueries in quantified expressions supported? A JDBC
- * Compliant driver always returns true.
- *
- * (No idea what this is, but we support a good deal of
- * subquerying.)
- *
- * @return true if so; false otherwise
- * @exception SQLException - if a database access error occurs
- */
- public boolean supportsSubqueriesInQuantifieds() throws SQLException
- {
- return true;
- }
-
- /**
- * Are correlated subqueries supported? A JDBC Compliant driver
- * always returns true.
- *
- * (a.k.a. subselect in from?)
- *
- * @return true if so; false otherwise
- * @exception SQLException - if a database access error occurs
- */
- public boolean supportsCorrelatedSubqueries() throws SQLException
- {
- return connection.haveMinimumServerVersion("7.1");
- }
-
- /**
- * Is SQL UNION supported?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsUnion() throws SQLException
- {
- return true; // since 6.3
- }
-
- /**
- * Is SQL UNION ALL supported?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsUnionAll() throws SQLException
- {
- return connection.haveMinimumServerVersion("7.1");
- }
-
- /**
- * In PostgreSQL, Cursors are only open within transactions.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsOpenCursorsAcrossCommit() throws SQLException
- {
- return false;
- }
-
- /**
- * Do we support open cursors across multiple transactions?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsOpenCursorsAcrossRollback() throws SQLException
- {
- return false;
- }
-
- /**
- * Can statements remain open across commits? They may, but
- * this driver cannot guarentee that. In further reflection.
- * we are talking a Statement object here, so the answer is
- * yes, since the Statement is only a vehicle to ExecSQL()
- *
- * @return true if they always remain open; false otherwise
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsOpenStatementsAcrossCommit() throws SQLException
- {
- return true;
- }
-
- /**
- * Can statements remain open across rollbacks? They may, but
- * this driver cannot guarentee that. In further contemplation,
- * we are talking a Statement object here, so the answer is yes,
- * since the Statement is only a vehicle to ExecSQL() in Connection
- *
- * @return true if they always remain open; false otherwise
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsOpenStatementsAcrossRollback() throws SQLException
- {
- return true;
- }
-
- /**
- * How many hex characters can you have in an inline binary literal
- *
- * @return the max literal length
- * @exception SQLException if a database access error occurs
- */
- public int getMaxBinaryLiteralLength() throws SQLException
- {
- return 0; // no limit
- }
-
- /**
- * What is the maximum length for a character literal
- * I suppose it is 8190 (8192 - 2 for the quotes)
- *
- * @return the max literal length
- * @exception SQLException if a database access error occurs
- */
- public int getMaxCharLiteralLength() throws SQLException
- {
- return 0; // no limit
- }
-
- /**
- * Whats the limit on column name length. The description of
- * pg_class would say '32' (length of pg_class.relname) - we
- * should probably do a query for this....but....
- *
- * @return the maximum column name length
- * @exception SQLException if a database access error occurs
- */
- public int getMaxColumnNameLength() throws SQLException
- {
- return 32;
- }
-
- /**
- * What is the maximum number of columns in a "GROUP BY" clause?
- *
- * @return the max number of columns
- * @exception SQLException if a database access error occurs
- */
- public int getMaxColumnsInGroupBy() throws SQLException
- {
- return 0; // no limit
- }
-
- /**
- * What's the maximum number of columns allowed in an index?
- * 6.0 only allowed one column, but 6.1 introduced multi-column
- * indices, so, theoretically, its all of them.
- *
- * @return max number of columns
- * @exception SQLException if a database access error occurs
- */
- public int getMaxColumnsInIndex() throws SQLException
- {
- return getMaxColumnsInTable();
- }
-
- /**
- * What's the maximum number of columns in an "ORDER BY clause?
- *
- * @return the max columns
- * @exception SQLException if a database access error occurs
- */
- public int getMaxColumnsInOrderBy() throws SQLException
- {
- return 0; // no limit
- }
-
- /**
- * What is the maximum number of columns in a "SELECT" list?
- *
- * @return the max columns
- * @exception SQLException if a database access error occurs
- */
- public int getMaxColumnsInSelect() throws SQLException
- {
- return 0; // no limit
- }
-
- /**
- * What is the maximum number of columns in a table? From the
- * CREATE TABLE reference page...
- *
- * <p>"The new class is created as a heap with no initial data. A
- * class can have no more than 1600 attributes (realistically,
- * this is limited by the fact that tuple sizes must be less than
- * 8192 bytes)..."
- *
- * @return the max columns
- * @exception SQLException if a database access error occurs
- */
- public int getMaxColumnsInTable() throws SQLException
- {
- return 1600;
- }
-
- /**
- * How many active connection can we have at a time to this
- * database? Well, since it depends on postmaster, which just
- * does a listen() followed by an accept() and fork(), its
- * basically very high. Unless the system runs out of processes,
- * it can be 65535 (the number of aux. ports on a TCP/IP system).
- * I will return 8192 since that is what even the largest system
- * can realistically handle,
- *
- * @return the maximum number of connections
- * @exception SQLException if a database access error occurs
- */
- public int getMaxConnections() throws SQLException
- {
- return 8192;
- }
-
- /**
- * What is the maximum cursor name length (the same as all
- * the other F***** identifiers!)
- *
- * @return max cursor name length in bytes
- * @exception SQLException if a database access error occurs
- */
- public int getMaxCursorNameLength() throws SQLException
- {
- return 32;
- }
-
- /**
- * Retrieves the maximum number of bytes for an index, including all
- * of the parts of the index.
- *
- * @return max index length in bytes, which includes the composite
- * of all the constituent parts of the index; a result of zero means
- * that there is no limit or the limit is not known
- * @exception SQLException if a database access error occurs
- */
- public int getMaxIndexLength() throws SQLException
- {
- return 0; // no limit (larger than an int anyway)
- }
-
- public int getMaxSchemaNameLength() throws SQLException
- {
- // XXX-Not Implemented
- return 0;
- }
-
- /**
- * What is the maximum length of a procedure name?
- * (length of pg_proc.proname used) - again, I really
- * should do a query here to get it.
- *
- * @return the max name length in bytes
- * @exception SQLException if a database access error occurs
- */
- public int getMaxProcedureNameLength() throws SQLException
- {
- return 32;
- }
-
- public int getMaxCatalogNameLength() throws SQLException
- {
- // XXX-Not Implemented
- return 0;
- }
-
- /**
- * What is the maximum length of a single row?
- *
- * @return max row size in bytes
- * @exception SQLException if a database access error occurs
- */
- public int getMaxRowSize() throws SQLException
- {
- if (connection.haveMinimumServerVersion("7.1"))
- return 1073741824; // 1 GB
- else
- return 8192; // XXX could be altered
- }
-
- /**
- * Did getMaxRowSize() include LONGVARCHAR and LONGVARBINARY
- * blobs? We don't handle blobs yet
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean doesMaxRowSizeIncludeBlobs() throws SQLException
- {
- return false;
- }
-
- /**
- * What is the maximum length of a SQL statement?
- *
- * @return max length in bytes
- * @exception SQLException if a database access error occurs
- */
- public int getMaxStatementLength() throws SQLException
- {
- if (connection.haveMinimumServerVersion("7.0"))
- return 0; // actually whatever fits in size_t
- else
- return 16384;
- }
-
- /**
- * How many active statements can we have open at one time to
- * this database? Basically, since each Statement downloads
- * the results as the query is executed, we can have many. However,
- * we can only really have one statement per connection going
- * at once (since they are executed serially) - so we return
- * one.
- *
- * @return the maximum
- * @exception SQLException if a database access error occurs
- */
- public int getMaxStatements() throws SQLException
- {
- return 1;
- }
-
- /**
- * What is the maximum length of a table name? This was found
- * from pg_class.relname length
- *
- * @return max name length in bytes
- * @exception SQLException if a database access error occurs
- */
- public int getMaxTableNameLength() throws SQLException
- {
- return 32;
- }
-
- /**
- * What is the maximum number of tables that can be specified
- * in a SELECT?
- *
- * @return the maximum
- * @exception SQLException if a database access error occurs
- */
- public int getMaxTablesInSelect() throws SQLException
- {
- return 0; // no limit
- }
-
- /**
- * What is the maximum length of a user name? Well, we generally
- * use UNIX like user names in PostgreSQL, so I think this would
- * be 8. However, showing the schema for pg_user shows a length
- * for username of 32.
- *
- * @return the max name length in bytes
- * @exception SQLException if a database access error occurs
- */
- public int getMaxUserNameLength() throws SQLException
- {
- return 32;
- }
-
-
- /**
- * What is the database's default transaction isolation level? We
- * do not support this, so all transactions are SERIALIZABLE.
- *
- * @return the default isolation level
- * @exception SQLException if a database access error occurs
- * @see Connection
- */
- public int getDefaultTransactionIsolation() throws SQLException
- {
- return Connection.TRANSACTION_READ_COMMITTED;
- }
-
- /**
- * Are transactions supported? If not, commit and rollback are noops
- * and the isolation level is TRANSACTION_NONE. We do support
- * transactions.
- *
- * @return true if transactions are supported
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsTransactions() throws SQLException
- {
- return true;
- }
-
- /**
- * Does the database support the given transaction isolation level?
- * We only support TRANSACTION_SERIALIZABLE and TRANSACTION_READ_COMMITTED
- *
- * @param level the values are defined in java.sql.Connection
- * @return true if so
- * @exception SQLException if a database access error occurs
- * @see Connection
- */
- public boolean supportsTransactionIsolationLevel(int level) throws SQLException
- {
- if (level == Connection.TRANSACTION_SERIALIZABLE ||
- level == Connection.TRANSACTION_READ_COMMITTED)
- return true;
- else
- return false;
- }
-
- /**
- * Are both data definition and data manipulation transactions
- * supported?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException
- {
- return true;
- }
-
- /**
- * Are only data manipulation statements withing a transaction
- * supported?
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean supportsDataManipulationTransactionsOnly() throws SQLException
- {
- return false;
- }
-
- /**
- * Does a data definition statement within a transaction force
- * the transaction to commit? I think this means something like:
- *
- * <p><pre>
- * CREATE TABLE T (A INT);
- * INSERT INTO T (A) VALUES (2);
- * BEGIN;
- * UPDATE T SET A = A + 1;
- * CREATE TABLE X (A INT);
- * SELECT A FROM T INTO X;
- * COMMIT;
- * </pre><p>
- *
- * does the CREATE TABLE call cause a commit? The answer is no.
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean dataDefinitionCausesTransactionCommit() throws SQLException
- {
- return false;
- }
-
- /**
- * Is a data definition statement within a transaction ignored?
- * It seems to be (from experiment in previous method)
- *
- * @return true if so
- * @exception SQLException if a database access error occurs
- */
- public boolean dataDefinitionIgnoredInTransactions() throws SQLException
- {
- return true;
- }
-
- /**
- * Get a description of stored procedures available in a catalog
- *
- * <p>Only procedure descriptions matching the schema and procedure
- * name criteria are returned. They are ordered by PROCEDURE_SCHEM
- * and PROCEDURE_NAME
- *
- * <p>Each procedure description has the following columns:
- * <ol>
- * <li><b>PROCEDURE_CAT</b> String => procedure catalog (may be null)
- * <li><b>PROCEDURE_SCHEM</b> String => procedure schema (may be null)
- * <li><b>PROCEDURE_NAME</b> String => procedure name
- * <li><b>Field 4</b> reserved (make it null)
- * <li><b>Field 5</b> reserved (make it null)
- * <li><b>Field 6</b> reserved (make it null)
- * <li><b>REMARKS</b> String => explanatory comment on the procedure
- * <li><b>PROCEDURE_TYPE</b> short => kind of procedure
- * <ul>
- * <li> procedureResultUnknown - May return a result
- * <li> procedureNoResult - Does not return a result
- * <li> procedureReturnsResult - Returns a result
- * </ul>
- * </ol>
- *
- * @param catalog - a catalog name; "" retrieves those without a
- * catalog; null means drop catalog name from criteria
- * @param schemaParrern - a schema name pattern; "" retrieves those
- * without a schema - we ignore this parameter
- * @param procedureNamePattern - a procedure name pattern
- * @return ResultSet - each row is a procedure description
- * @exception SQLException if a database access error occurs
- */
- public java.sql.ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException
- {
- // the field descriptors for the new ResultSet
- Field f[] = new Field[8];
- java.sql.ResultSet r; // ResultSet for the SQL query that we need to do
- Vector v = new Vector(); // The new ResultSet tuple stuff
-
- f[0] = new Field(connection, "PROCEDURE_CAT", iVarcharOid, 32);
- f[1] = new Field(connection, "PROCEDURE_SCHEM", iVarcharOid, 32);
- f[2] = new Field(connection, "PROCEDURE_NAME", iVarcharOid, 32);
- f[3] = f[4] = f[5] = new Field(connection,"reserved",iVarcharOid,32); // null; // reserved, must be null for now
- f[6] = new Field(connection, "REMARKS", iVarcharOid, 8192);
- f[7] = new Field(connection, "PROCEDURE_TYPE", iInt2Oid, 2);
-
- // If the pattern is null, then set it to the default
- if(procedureNamePattern==null)
- procedureNamePattern="%";
-
- r = connection.ExecSQL("select proname, proretset from pg_proc where proname like '"+procedureNamePattern.toLowerCase()+"' order by proname");
-
- while (r.next())
- {
- byte[][] tuple = new byte[8][0];
-
- tuple[0] = null; // Catalog name
- tuple[1] = null; // Schema name
- tuple[2] = r.getBytes(1); // Procedure name
- tuple[3] = tuple[4] = tuple[5] = null; // Reserved
- tuple[6] = null; // Remarks
-
- if (r.getBoolean(2))
- tuple[7] = Integer.toString(java.sql.DatabaseMetaData.procedureReturnsResult).getBytes();
- else
- tuple[7] = Integer.toString(java.sql.DatabaseMetaData.procedureNoResult).getBytes();
-
- v.addElement(tuple);
- }
- return new ResultSet(connection, f, v, "OK", 1);
- }
-
- /**
- * Get a description of a catalog's stored procedure parameters
- * and result columns.
- *
- * <p>Only descriptions matching the schema, procedure and parameter
- * name criteria are returned. They are ordered by PROCEDURE_SCHEM
- * and PROCEDURE_NAME. Within this, the return value, if any, is
- * first. Next are the parameter descriptions in call order. The
- * column descriptions follow in column number order.
- *
- * <p>Each row in the ResultSet is a parameter description or column
- * description with the following fields:
- * <ol>
- * <li><b>PROCEDURE_CAT</b> String => procedure catalog (may be null)
- * <li><b>PROCEDURE_SCHE</b>M String => procedure schema (may be null)
- * <li><b>PROCEDURE_NAME</b> String => procedure name
- * <li><b>COLUMN_NAME</b> String => column/parameter name
- * <li><b>COLUMN_TYPE</b> Short => kind of column/parameter:
- * <ul><li>procedureColumnUnknown - nobody knows
- * <li>procedureColumnIn - IN parameter
- * <li>procedureColumnInOut - INOUT parameter
- * <li>procedureColumnOut - OUT parameter
- * <li>procedureColumnReturn - procedure return value
- * <li>procedureColumnResult - result column in ResultSet
- * </ul>
- * <li><b>DATA_TYPE</b> short => SQL type from java.sql.Types
- * <li><b>TYPE_NAME</b> String => SQL type name
- * <li><b>PRECISION</b> int => precision
- * <li><b>LENGTH</b> int => length in bytes of data
- * <li><b>SCALE</b> short => scale
- * <li><b>RADIX</b> short => radix
- * <li><b>NULLABLE</b> short => can it contain NULL?
- * <ul><li>procedureNoNulls - does not allow NULL values
- * <li>procedureNullable - allows NULL values
- * <li>procedureNullableUnknown - nullability unknown
- * <li><b>REMARKS</b> String => comment describing parameter/column
- * </ol>
- * @param catalog This is ignored in org.postgresql, advise this is set to null
- * @param schemaPattern This is ignored in org.postgresql, advise this is set to null
- * @param procedureNamePattern a procedure name pattern
- * @param columnNamePattern a column name pattern
- * @return each row is a stored procedure parameter or column description
- * @exception SQLException if a database-access error occurs
- * @see #getSearchStringEscape
- */
- // Implementation note: This is required for Borland's JBuilder to work
- public java.sql.ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException
- {
- if(procedureNamePattern==null)
- procedureNamePattern="%";
-
- if(columnNamePattern==null)
- columnNamePattern="%";
-
- // for now, this returns an empty result set.
- Field f[] = new Field[13];
- ResultSet r; // ResultSet for the SQL query that we need to do
- Vector v = new Vector(); // The new ResultSet tuple stuff
-
- f[0] = new Field(connection, "PROCEDURE_CAT", iVarcharOid, 32);
- f[1] = new Field(connection, "PROCEDURE_SCHEM", iVarcharOid, 32);
- f[2] = new Field(connection, "PROCEDURE_NAME", iVarcharOid, 32);
- f[3] = new Field(connection, "COLUMN_NAME", iVarcharOid, 32);
- f[4] = new Field(connection, "COLUMN_TYPE", iInt2Oid, 2);
- f[5] = new Field(connection, "DATA_TYPE", iInt2Oid, 2);
- f[6] = new Field(connection, "TYPE_NAME", iVarcharOid, 32);
- f[7] = new Field(connection, "PRECISION", iInt4Oid, 4);
- f[8] = new Field(connection, "LENGTH", iInt4Oid, 4);
- f[9] = new Field(connection, "SCALE", iInt2Oid, 2);
- f[10] = new Field(connection, "RADIX", iInt2Oid, 2);
- f[11] = new Field(connection, "NULLABLE", iInt2Oid, 2);
- f[12] = new Field(connection, "REMARKS", iVarcharOid, 32);
-
- // add query loop here
-
- return new ResultSet(connection, f, v, "OK", 1);
- }
-
- /**
- * Get a description of tables available in a catalog.
- *
- * <p>Only table descriptions matching the catalog, schema, table
- * name and type criteria are returned. They are ordered by
- * TABLE_TYPE, TABLE_SCHEM and TABLE_NAME.
- *
- * <p>Each table description has the following columns:
- *
- * <ol>
- * <li><b>TABLE_CAT</b> String => table catalog (may be null)
- * <li><b>TABLE_SCHEM</b> String => table schema (may be null)
- * <li><b>TABLE_NAME</b> String => table name
- * <li><b>TABLE_TYPE</b> String => table type. Typical types are "TABLE",
- * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL
- * TEMPORARY", "ALIAS", "SYNONYM".
- * <li><b>REMARKS</b> String => explanatory comment on the table
- * </ol>
- *
- * <p>The valid values for the types parameter are:
- * "TABLE", "INDEX", "SEQUENCE", "SYSTEM TABLE" and "SYSTEM INDEX"
- *
- * @param catalog a catalog name; For org.postgresql, this is ignored, and
- * should be set to null
- * @param schemaPattern a schema name pattern; For org.postgresql, this is ignored, and
- * should be set to null
- * @param tableNamePattern a table name pattern. For all tables this should be "%"
- * @param types a list of table types to include; null returns
- * all types
- * @return each row is a table description
- * @exception SQLException if a database-access error occurs.
- */
- public java.sql.ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String types[]) throws SQLException
- {
- // Handle default value for types
- if(types==null)
- types = defaultTableTypes;
-
- if(tableNamePattern==null)
- tableNamePattern="%";
-
- // the field descriptors for the new ResultSet
- Field f[] = new Field[5];
- java.sql.ResultSet r; // ResultSet for the SQL query that we need to do
- Vector v = new Vector(); // The new ResultSet tuple stuff
-
- f[0] = new Field(connection, "TABLE_CAT", iVarcharOid, 32);
- f[1] = new Field(connection, "TABLE_SCHEM", iVarcharOid, 32);
- f[2] = new Field(connection, "TABLE_NAME", iVarcharOid, 32);
- f[3] = new Field(connection, "TABLE_TYPE", iVarcharOid, 32);
- f[4] = new Field(connection, "REMARKS", iVarcharOid, 32);
-
- // Now form the query
- StringBuffer sql = new StringBuffer("select relname,oid,relkind from pg_class where (");
-
- boolean notFirst=false;
- for(int i=0;i<types.length;i++) {
- for(int j=0;j<getTableTypes.length;j++)
- if(getTableTypes[j][0].equals(types[i])) {
- if(notFirst)
- sql.append(" or ");
- sql.append(getTableTypes[j][1]);
- notFirst=true;
- }
- }
-
- // Added by Stefan Andreasen <stefan@linux.kapow.dk>
- // Now take the pattern into account
- sql.append(") and relname like '");
- sql.append(tableNamePattern.toLowerCase());
- sql.append("' order by relkind, relname");
-
- // Now run the query
- r = connection.ExecSQL(sql.toString());
-
- while (r.next())
- {
- byte[][] tuple = new byte[5][0];
-
- // Fetch the description for the table (if any)
- String getDescriptionStatement =
- connection.haveMinimumServerVersion("7.2") ?
- "select obj_description("+r.getInt(2)+",'pg_class')" :
- "select description from pg_description where objoid=" + r.getInt(2);
-
- java.sql.ResultSet dr = connection.ExecSQL(getDescriptionStatement);
-
- byte remarks[] = null;
-
- if(((org.postgresql.ResultSet)dr).getTupleCount()==1) {
- dr.next();
- remarks = dr.getBytes(1);
- }
- dr.close();
-
- String relKind;
- switch (r.getBytes(3)[0]) {
- case (byte) 'r':
- relKind = "TABLE";
- break;
- case (byte) 'i':
- relKind = "INDEX";
- break;
- case (byte) 'S':
- relKind = "SEQUENCE";
- break;
- case (byte) 'v':
- relKind = "VIEW";
- break;
- default:
- relKind = null;
- }
-
- tuple[0] = null; // Catalog name
- tuple[1] = null; // Schema name
- tuple[2] = r.getBytes(1); // Table name
- tuple[3] = (relKind==null) ? null : relKind.getBytes(); // Table type
- tuple[4] = remarks; // Remarks
- v.addElement(tuple);
- }
- r.close();
- return new ResultSet(connection, f, v, "OK", 1);
- }
-
- // This array contains the valid values for the types argument
- // in getTables().
- //
- // Each supported type consists of it's name, and the sql where
- // clause to retrieve that value.
- //
- // IMPORTANT: the query must be enclosed in ( )
- private static final String getTableTypes[][] = {
- {"TABLE", "(relkind='r' and relhasrules='f' and relname !~ '^pg_' and relname !~ '^xinv')"},
- {"VIEW", "(relkind='v' and relname !~ '^pg_')"},
- {"INDEX", "(relkind='i' and relname !~ '^pg_')"},
- {"SEQUENCE", "(relkind='S' and relname !~ '^pg_')"},
- {"SYSTEM TABLE", "(relkind='r' and relname ~ '^pg_')"},
- {"SYSTEM INDEX", "(relkind='i' and relname ~ '^pg_')"}
- };
-
- // These are the default tables, used when NULL is passed to getTables
- // The choice of these provide the same behaviour as psql's \d
- private static final String defaultTableTypes[] = {
- "TABLE","VIEW","INDEX","SEQUENCE"
- };
-
- /**
- * Get the schema names available in this database. The results
- * are ordered by schema name.
- *
- * <P>The schema column is:
- * <OL>
- * <LI><B>TABLE_SCHEM</B> String => schema name
- * </OL>
- *
- * @return ResultSet each row has a single String column that is a
- * schema name
- */
- public java.sql.ResultSet getSchemas() throws SQLException
- {
- // We don't use schemas, so we simply return a single schema name "".
- //
- Field f[] = new Field[1];
- Vector v = new Vector();
- byte[][] tuple = new byte[1][0];
- f[0] = new Field(connection,"TABLE_SCHEM",iVarcharOid,32);
- tuple[0] = "".getBytes();
- v.addElement(tuple);
- return new ResultSet(connection,f,v,"OK",1);
- }
-
- /**
- * Get the catalog names available in this database. The results
- * are ordered by catalog name.
- *
- * <P>The catalog column is:
- * <OL>
- * <LI><B>TABLE_CAT</B> String => catalog name
- * </OL>
- *
- * @return ResultSet each row has a single String column that is a
- * catalog name
- */
- public java.sql.ResultSet getCatalogs() throws SQLException
- {
- return connection.createStatement().executeQuery("select datname as TABLE_CAT from pg_database;");
- }
-
- /**
- * Get the table types available in this database. The results
- * are ordered by table type.
- *
- * <P>The table type is:
- * <OL>
- * <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
- * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
- * "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
- * </OL>
- *
- * @return ResultSet each row has a single String column that is a
- * table type
- */
- public java.sql.ResultSet getTableTypes() throws SQLException
- {
- Field f[] = new Field[1];
- Vector v = new Vector();
- f[0] = new Field(connection,new String("TABLE_TYPE"),iVarcharOid,32);
- for(int i=0;i<getTableTypes.length;i++) {
- byte[][] tuple = new byte[1][0];
- tuple[0] = getTableTypes[i][0].getBytes();
- v.addElement(tuple);
- }
- return new ResultSet(connection,f,v,"OK",1);
- }
-
- /**
- * Get a description of table columns available in a catalog.
- *
- * <P>Only column descriptions matching the catalog, schema, table
- * and column name criteria are returned. They are ordered by
- * TABLE_SCHEM, TABLE_NAME and ORDINAL_POSITION.
- *
- * <P>Each column description has the following columns:
- * <OL>
- * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
- * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
- * <LI><B>TABLE_NAME</B> String => table name
- * <LI><B>COLUMN_NAME</B> String => column name
- * <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
- * <LI><B>TYPE_NAME</B> String => Data source dependent type name
- * <LI><B>COLUMN_SIZE</B> int => column size. For char or date
- * types this is the maximum number of characters, for numeric or
- * decimal types this is precision.
- * <LI><B>BUFFER_LENGTH</B> is not used.
- * <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits
- * <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
- * <LI><B>NULLABLE</B> int => is NULL allowed?
- * <UL>
- * <LI> columnNoNulls - might not allow NULL values
- * <LI> columnNullable - definitely allows NULL values
- * <LI> columnNullableUnknown - nullability unknown
- * </UL>
- * <LI><B>REMARKS</B> String => comment describing column (may be null)
- * <LI><B>COLUMN_DEF</B> String => default value (may be null)
- * <LI><B>SQL_DATA_TYPE</B> int => unused
- * <LI><B>SQL_DATETIME_SUB</B> int => unused
- * <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
- * maximum number of bytes in the column
- * <LI><B>ORDINAL_POSITION</B> int => index of column in table
- * (starting at 1)
- * <LI><B>IS_NULLABLE</B> String => "NO" means column definitely
- * does not allow NULL values; "YES" means the column might
- * allow NULL values. An empty string means nobody knows.
- * </OL>
- *
- * @param catalog a catalog name; "" retrieves those without a catalog
- * @param schemaPattern a schema name pattern; "" retrieves those
- * without a schema
- * @param tableNamePattern a table name pattern
- * @param columnNamePattern a column name pattern
- * @return ResultSet each row is a column description
- * @see #getSearchStringEscape
- */
- public java.sql.ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException
- {
- Vector v = new Vector(); // The new ResultSet tuple stuff
- Field f[] = new Field[18]; // The field descriptors for the new ResultSet
-
- f[0] = new Field(connection, "TABLE_CAT", iVarcharOid, 32);
- f[1] = new Field(connection, "TABLE_SCHEM", iVarcharOid, 32);
- f[2] = new Field(connection, "TABLE_NAME", iVarcharOid, 32);
- f[3] = new Field(connection, "COLUMN_NAME", iVarcharOid, 32);
- f[4] = new Field(connection, "DATA_TYPE", iInt2Oid, 2);
- f[5] = new Field(connection, "TYPE_NAME", iVarcharOid, 32);
- f[6] = new Field(connection, "COLUMN_SIZE", iInt4Oid, 4);
- f[7] = new Field(connection, "BUFFER_LENGTH", iVarcharOid, 32);
- f[8] = new Field(connection, "DECIMAL_DIGITS", iInt4Oid, 4);
- f[9] = new Field(connection, "NUM_PREC_RADIX", iInt4Oid, 4);
- f[10] = new Field(connection, "NULLABLE", iInt4Oid, 4);
- f[11] = new Field(connection, "REMARKS", iVarcharOid, 32);
- f[12] = new Field(connection, "COLUMN_DEF", iVarcharOid, 32);
- f[13] = new Field(connection, "SQL_DATA_TYPE", iInt4Oid, 4);
- f[14] = new Field(connection, "SQL_DATETIME_SUB", iInt4Oid, 4);
- f[15] = new Field(connection, "CHAR_OCTET_LENGTH", iVarcharOid, 32);
- f[16] = new Field(connection, "ORDINAL_POSITION", iInt4Oid,4);
- f[17] = new Field(connection, "IS_NULLABLE", iVarcharOid, 32);
-
- StringBuffer sql = new StringBuffer(512);
-
- /* Build a >= 7.1 SQL statement to list all columns */
- sql.append("select " +
- (connection.haveMinimumServerVersion("7.2") ? "a.attrelid, " : "a.oid, ") +
- " c.relname, " +
- " a.attname, " +
- " a.atttypid, " +
- " a.attnum, " +
- " a.attnotnull, " +
- " a.attlen, " +
- " a.atttypmod, " +
- " d.adsrc, " +
- " t.typname, " +
- /* Use the new col_description in 7.2 or an additional outer join in 7.1 */
- (connection.haveMinimumServerVersion("7.2") ? "col_description(a.attrelid, a.attnum) " : "e.description ") +
- "from" +
- " (" +
- " (pg_class c inner join pg_attribute a on" +
- " (" +
- " a.attrelid=c.oid");
-
- if ((tableNamePattern != null) && ! tableNamePattern.equals("%")) {
- sql.append(" and c.relname like \'" + tableNamePattern + "\'");
- }
-
- if ((columnNamePattern != null) && ! columnNamePattern.equals("%")) {
- sql.append(" and a.attname like \'" + columnNamePattern + "\'");
- }
-
- sql.append(
- " and a.attnum > 0" +
- " )" +
- " ) inner join pg_type t on" +
- " (" +
- " t.oid = a.atttypid" +
- " )" +
- " )" +
- " left outer join pg_attrdef d on" +
- " (" +
- " c.oid = d.adrelid" +
- " and a.attnum = d.adnum" +
- " ) ");
-
- if (!connection.haveMinimumServerVersion("7.2")) {
- /* Only for 7.1 */
+ Connection connection; // The connection association
+
+ // These define various OID's. Hopefully they will stay constant.
+ static final int iVarcharOid = 1043; // OID for varchar
+ static final int iBoolOid = 16; // OID for bool
+ static final int iInt2Oid = 21; // OID for int2
+ static final int iInt4Oid = 23; // OID for int4
+ static final int VARHDRSZ = 4; // length for int4
+
+ public DatabaseMetaData(Connection conn)
+ {
+ this.connection = conn;
+ }
+
+ /**
+ * Can all the procedures returned by getProcedures be called
+ * by the current user?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean allProceduresAreCallable() throws SQLException
+ {
+ return true; // For now...
+ }
+
+ /**
+ * Can all the tables returned by getTable be SELECTed by
+ * the current user?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean allTablesAreSelectable() throws SQLException
+ {
+ return true; // For now...
+ }
+
+ /**
+ * What is the URL for this database?
+ *
+ * @return the url or null if it cannott be generated
+ * @exception SQLException if a database access error occurs
+ */
+ public String getURL() throws SQLException
+ {
+ return connection.getURL();
+ }
+
+ /**
+ * What is our user name as known to the database?
+ *
+ * @return our database user name
+ * @exception SQLException if a database access error occurs
+ */
+ public String getUserName() throws SQLException
+ {
+ return connection.getUserName();
+ }
+
+ /**
+ * Is the database in read-only mode?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean isReadOnly() throws SQLException
+ {
+ return connection.isReadOnly();
+ }
+
+ /**
+ * Are NULL values sorted high?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean nullsAreSortedHigh() throws SQLException
+ {
+ return connection.haveMinimumServerVersion("7.2");
+ }
+
+ /**
+ * Are NULL values sorted low?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean nullsAreSortedLow() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Are NULL values sorted at the start regardless of sort order?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean nullsAreSortedAtStart() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Are NULL values sorted at the end regardless of sort order?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean nullsAreSortedAtEnd() throws SQLException
+ {
+ return ! connection.haveMinimumServerVersion("7.2");
+ }
+
+ /**
+ * What is the name of this database product - we hope that it is
+ * PostgreSQL, so we return that explicitly.
+ *
+ * @return the database product name
+ * @exception SQLException if a database access error occurs
+ */
+ public String getDatabaseProductName() throws SQLException
+ {
+ return "PostgreSQL";
+ }
+
+ /**
+ * What is the version of this database product.
+ *
+ * @return the database version
+ * @exception SQLException if a database access error occurs
+ */
+ public String getDatabaseProductVersion() throws SQLException
+ {
+ return connection.getDBVersionNumber();
+ }
+
+ /**
+ * What is the name of this JDBC driver? If we don't know this
+ * we are doing something wrong!
+ *
+ * @return the JDBC driver name
+ * @exception SQLException why?
+ */
+ public String getDriverName() throws SQLException
+ {
+ return "PostgreSQL Native Driver";
+ }
+
+ /**
+ * What is the version string of this JDBC driver? Again, this is
+ * static.
+ *
+ * @return the JDBC driver name.
+ * @exception SQLException why?
+ */
+ public String getDriverVersion() throws SQLException
+ {
+ return connection.this_driver.getVersion();
+ }
+
+ /**
+ * What is this JDBC driver's major version number?
+ *
+ * @return the JDBC driver major version
+ */
+ public int getDriverMajorVersion()
+ {
+ return connection.this_driver.getMajorVersion();
+ }
+
+ /**
+ * What is this JDBC driver's minor version number?
+ *
+ * @return the JDBC driver minor version
+ */
+ public int getDriverMinorVersion()
+ {
+ return connection.this_driver.getMinorVersion();
+ }
+
+ /**
+ * Does the database store tables in a local file? No - it
+ * stores them in a file on the server.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean usesLocalFiles() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Does the database use a file for each table? Well, not really,
+ * since it doesnt use local files.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean usesLocalFilePerTable() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Does the database treat mixed case unquoted SQL identifiers
+ * as case sensitive and as a result store them in mixed case?
+ * A JDBC-Compliant driver will always return false.
+ *
+ * <p>Predicament - what do they mean by "SQL identifiers" - if it
+ * means the names of the tables and columns, then the answers
+ * given below are correct - otherwise I don't know.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsMixedCaseIdentifiers() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Does the database treat mixed case unquoted SQL identifiers as
+ * case insensitive and store them in upper case?
+ *
+ * @return true if so
+ */
+ public boolean storesUpperCaseIdentifiers() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Does the database treat mixed case unquoted SQL identifiers as
+ * case insensitive and store them in lower case?
+ *
+ * @return true if so
+ */
+ public boolean storesLowerCaseIdentifiers() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * Does the database treat mixed case unquoted SQL identifiers as
+ * case insensitive and store them in mixed case?
+ *
+ * @return true if so
+ */
+ public boolean storesMixedCaseIdentifiers() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Does the database treat mixed case quoted SQL identifiers as
+ * case sensitive and as a result store them in mixed case? A
+ * JDBC compliant driver will always return true.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * Does the database treat mixed case quoted SQL identifiers as
+ * case insensitive and store them in upper case?
+ *
+ * @return true if so
+ */
+ public boolean storesUpperCaseQuotedIdentifiers() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Does the database treat mixed case quoted SQL identifiers as case
+ * insensitive and store them in lower case?
+ *
+ * @return true if so
+ */
+ public boolean storesLowerCaseQuotedIdentifiers() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Does the database treat mixed case quoted SQL identifiers as case
+ * insensitive and store them in mixed case?
+ *
+ * @return true if so
+ */
+ public boolean storesMixedCaseQuotedIdentifiers() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * What is the string used to quote SQL identifiers? This returns
+ * a space if identifier quoting isn't supported. A JDBC Compliant
+ * driver will always use a double quote character.
+ *
+ * @return the quoting string
+ * @exception SQLException if a database access error occurs
+ */
+ public String getIdentifierQuoteString() throws SQLException
+ {
+ return "\"";
+ }
+
+ /**
+ * Get a comma separated list of all a database's SQL keywords that
+ * are NOT also SQL92 keywords.
+ *
+ * <p>Within PostgreSQL, the keywords are found in
+ * src/backend/parser/keywords.c
+ *
+ * <p>For SQL Keywords, I took the list provided at
+ * <a href="http://web.dementia.org/~shadow/sql/sql3bnf.sep93.txt">
+ * http://web.dementia.org/~shadow/sql/sql3bnf.sep93.txt</a>
+ * which is for SQL3, not SQL-92, but it is close enough for
+ * this purpose.
+ *
+ * @return a comma separated list of keywords we use
+ * @exception SQLException if a database access error occurs
+ */
+ public String getSQLKeywords() throws SQLException
+ {
+ return "abort,acl,add,aggregate,append,archive,arch_store,backward,binary,change,cluster,copy,database,delimiters,do,extend,explain,forward,heavy,index,inherits,isnull,light,listen,load,merge,nothing,notify,notnull,oids,purge,rename,replace,retrieve,returns,rule,recipe,setof,stdin,stdout,store,vacuum,verbose,version";
+ }
+
+ public String getNumericFunctions() throws SQLException
+ {
+ // XXX-Not Implemented
+ return "";
+ }
+
+ public String getStringFunctions() throws SQLException
+ {
+ // XXX-Not Implemented
+ return "";
+ }
+
+ public String getSystemFunctions() throws SQLException
+ {
+ // XXX-Not Implemented
+ return "";
+ }
+
+ public String getTimeDateFunctions() throws SQLException
+ {
+ // XXX-Not Implemented
+ return "";
+ }
+
+ /**
+ * This is the string that can be used to escape '_' and '%' in
+ * a search string pattern style catalog search parameters
+ *
+ * @return the string used to escape wildcard characters
+ * @exception SQLException if a database access error occurs
+ */
+ public String getSearchStringEscape() throws SQLException
+ {
+ return "\\";
+ }
+
+ /**
+ * Get all the "extra" characters that can be used in unquoted
+ * identifier names (those beyond a-zA-Z0-9 and _)
+ *
+ * <p>From the file src/backend/parser/scan.l, an identifier is
+ * {letter}{letter_or_digit} which makes it just those listed
+ * above.
+ *
+ * @return a string containing the extra characters
+ * @exception SQLException if a database access error occurs
+ */
+ public String getExtraNameCharacters() throws SQLException
+ {
+ return "";
+ }
+
+ /**
+ * Is "ALTER TABLE" with an add column supported?
+ * Yes for PostgreSQL 6.1
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsAlterTableWithAddColumn() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * Is "ALTER TABLE" with a drop column supported?
+ * Peter 10/10/2000 This was set to true, but 7.1devel doesn't support it!
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsAlterTableWithDropColumn() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Is column aliasing supported?
+ *
+ * <p>If so, the SQL AS clause can be used to provide names for
+ * computed columns or to provide alias names for columns as
+ * required. A JDBC Compliant driver always returns true.
+ *
+ * <p>e.g.
+ *
+ * <br><pre>
+ * select count(C) as C_COUNT from T group by C;
+ *
+ * </pre><br>
+ * should return a column named as C_COUNT instead of count(C)
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsColumnAliasing() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * Are concatenations between NULL and non-NULL values NULL? A
+ * JDBC Compliant driver always returns true
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean nullPlusNonNullIsNull() throws SQLException
+ {
+ return true;
+ }
+
+ public boolean supportsConvert() throws SQLException
+ {
+ // XXX-Not Implemented
+ return false;
+ }
+
+ public boolean supportsConvert(int fromType, int toType) throws SQLException
+ {
+ // XXX-Not Implemented
+ return false;
+ }
+
+ /**
+ * Are table correlation names supported? A JDBC Compliant
+ * driver always returns true.
+ *
+ * @return true if so; false otherwise
+ * @exception SQLException - if a database access error occurs
+ */
+ public boolean supportsTableCorrelationNames() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * If table correlation names are supported, are they restricted to
+ * be different from the names of the tables?
+ *
+ * @return true if so; false otherwise
+ * @exception SQLException - if a database access error occurs
+ */
+ public boolean supportsDifferentTableCorrelationNames() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Are expressions in "ORDER BY" lists supported?
+ *
+ * <br>e.g. select * from t order by a + b;
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsExpressionsInOrderBy() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * Can an "ORDER BY" clause use columns not in the SELECT?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsOrderByUnrelated() throws SQLException
+ {
+ return connection.haveMinimumServerVersion("6.4");
+ }
+
+ /**
+ * Is some form of "GROUP BY" clause supported?
+ * I checked it, and yes it is.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsGroupBy() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * Can a "GROUP BY" clause use columns not in the SELECT?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsGroupByUnrelated() throws SQLException
+ {
+ return connection.haveMinimumServerVersion("6.4");
+ }
+
+ /**
+ * Can a "GROUP BY" clause add columns not in the SELECT provided
+ * it specifies all the columns in the SELECT? Does anyone actually
+ * understand what they mean here?
+ *
+ * (I think this is a subset of the previous function. -- petere)
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsGroupByBeyondSelect() throws SQLException
+ {
+ return supportsGroupByUnrelated();
+ }
+
+ /**
+ * Is the escape character in "LIKE" clauses supported? A
+ * JDBC compliant driver always returns true.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsLikeEscapeClause() throws SQLException
+ {
+ return connection.haveMinimumServerVersion("7.1");
+ }
+
+ /**
+ * Are multiple ResultSets from a single execute supported?
+ * Well, I implemented it, but I dont think this is possible from
+ * the back ends point of view.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsMultipleResultSets() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Can we have multiple transactions open at once (on different
+ * connections?)
+ * I guess we can have, since Im relying on it.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsMultipleTransactions() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * Can columns be defined as non-nullable. A JDBC Compliant driver
+ * always returns true.
+ *
+ * <p>This changed from false to true in v6.2 of the driver, as this
+ * support was added to the backend.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsNonNullableColumns() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * Does this driver support the minimum ODBC SQL grammar. This
+ * grammar is defined at:
+ *
+ * <p><a href="http://www.microsoft.com/msdn/sdk/platforms/doc/odbc/src/intropr.htm">http://www.microsoft.com/msdn/sdk/platforms/doc/odbc/src/intropr.htm</a>
+ *
+ * <p>In Appendix C. From this description, we seem to support the
+ * ODBC minimal (Level 0) grammar.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsMinimumSQLGrammar() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * Does this driver support the Core ODBC SQL grammar. We need
+ * SQL-92 conformance for this.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsCoreSQLGrammar() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Does this driver support the Extended (Level 2) ODBC SQL
+ * grammar. We don't conform to the Core (Level 1), so we can't
+ * conform to the Extended SQL Grammar.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsExtendedSQLGrammar() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Does this driver support the ANSI-92 entry level SQL grammar?
+ * All JDBC Compliant drivers must return true. We currently
+ * report false until 'schema' support is added. Then this
+ * should be changed to return true, since we will be mostly
+ * compliant (probably more compliant than many other databases)
+ * And since this is a requirement for all JDBC drivers we
+ * need to get to the point where we can return true.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsANSI92EntryLevelSQL() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Does this driver support the ANSI-92 intermediate level SQL
+ * grammar?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsANSI92IntermediateSQL() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Does this driver support the ANSI-92 full SQL grammar?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsANSI92FullSQL() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Is the SQL Integrity Enhancement Facility supported?
+ * I haven't seen this mentioned anywhere, so I guess not
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsIntegrityEnhancementFacility() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Is some form of outer join supported?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsOuterJoins() throws SQLException
+ {
+ return connection.haveMinimumServerVersion("7.1");
+ }
+
+ /**
+ * Are full nexted outer joins supported?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsFullOuterJoins() throws SQLException
+ {
+ return connection.haveMinimumServerVersion("7.1");
+ }
+
+ /**
+ * Is there limited support for outer joins?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsLimitedOuterJoins() throws SQLException
+ {
+ return supportsFullOuterJoins();
+ }
+
+ /**
+ * What is the database vendor's preferred term for "schema"?
+ * PostgreSQL doesn't have schemas, but when it does, we'll use the
+ * term "schema".
+ *
+ * @return the vendor term
+ * @exception SQLException if a database access error occurs
+ */
+ public String getSchemaTerm() throws SQLException
+ {
+ return "schema";
+ }
+
+ /**
+ * What is the database vendor's preferred term for "procedure"?
+ * Traditionally, "function" has been used.
+ *
+ * @return the vendor term
+ * @exception SQLException if a database access error occurs
+ */
+ public String getProcedureTerm() throws SQLException
+ {
+ return "function";
+ }
+
+ /**
+ * What is the database vendor's preferred term for "catalog"?
+ *
+ * @return the vendor term
+ * @exception SQLException if a database access error occurs
+ */
+ public String getCatalogTerm() throws SQLException
+ {
+ return "database";
+ }
+
+ /**
+ * Does a catalog appear at the start of a qualified table name?
+ * (Otherwise it appears at the end).
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean isCatalogAtStart() throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented();
+ }
+
+ /**
+ * What is the Catalog separator.
+ *
+ * @return the catalog separator string
+ * @exception SQLException if a database access error occurs
+ */
+ public String getCatalogSeparator() throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented();
+ }
+
+ /**
+ * Can a schema name be used in a data manipulation statement? Nope.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsSchemasInDataManipulation() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Can a schema name be used in a procedure call statement? Nope.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsSchemasInProcedureCalls() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Can a schema be used in a table definition statement? Nope.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsSchemasInTableDefinitions() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Can a schema name be used in an index definition statement?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsSchemasInIndexDefinitions() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Can a schema name be used in a privilege definition statement?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Can a catalog name be used in a data manipulation statement?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsCatalogsInDataManipulation() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Can a catalog name be used in a procedure call statement?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsCatalogsInProcedureCalls() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Can a catalog name be used in a table definition statement?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsCatalogsInTableDefinitions() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Can a catalog name be used in an index definition?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsCatalogsInIndexDefinitions() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Can a catalog name be used in a privilege definition statement?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * We support cursors for gets only it seems. I dont see a method
+ * to get a positioned delete.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsPositionedDelete() throws SQLException
+ {
+ return false; // For now...
+ }
+
+ /**
+ * Is positioned UPDATE supported?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsPositionedUpdate() throws SQLException
+ {
+ return false; // For now...
+ }
+
+ /**
+ * Is SELECT for UPDATE supported?
+ *
+ * @return true if so; false otherwise
+ * @exception SQLException - if a database access error occurs
+ */
+ public boolean supportsSelectForUpdate() throws SQLException
+ {
+ return connection.haveMinimumServerVersion("6.5");
+ }
+
+ /**
+ * Are stored procedure calls using the stored procedure escape
+ * syntax supported?
+ *
+ * @return true if so; false otherwise
+ * @exception SQLException - if a database access error occurs
+ */
+ public boolean supportsStoredProcedures() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Are subqueries in comparison expressions supported? A JDBC
+ * Compliant driver always returns true.
+ *
+ * @return true if so; false otherwise
+ * @exception SQLException - if a database access error occurs
+ */
+ public boolean supportsSubqueriesInComparisons() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * Are subqueries in 'exists' expressions supported? A JDBC
+ * Compliant driver always returns true.
+ *
+ * @return true if so; false otherwise
+ * @exception SQLException - if a database access error occurs
+ */
+ public boolean supportsSubqueriesInExists() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * Are subqueries in 'in' statements supported? A JDBC
+ * Compliant driver always returns true.
+ *
+ * @return true if so; false otherwise
+ * @exception SQLException - if a database access error occurs
+ */
+ public boolean supportsSubqueriesInIns() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * Are subqueries in quantified expressions supported? A JDBC
+ * Compliant driver always returns true.
+ *
+ * (No idea what this is, but we support a good deal of
+ * subquerying.)
+ *
+ * @return true if so; false otherwise
+ * @exception SQLException - if a database access error occurs
+ */
+ public boolean supportsSubqueriesInQuantifieds() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * Are correlated subqueries supported? A JDBC Compliant driver
+ * always returns true.
+ *
+ * (a.k.a. subselect in from?)
+ *
+ * @return true if so; false otherwise
+ * @exception SQLException - if a database access error occurs
+ */
+ public boolean supportsCorrelatedSubqueries() throws SQLException
+ {
+ return connection.haveMinimumServerVersion("7.1");
+ }
+
+ /**
+ * Is SQL UNION supported?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsUnion() throws SQLException
+ {
+ return true; // since 6.3
+ }
+
+ /**
+ * Is SQL UNION ALL supported?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsUnionAll() throws SQLException
+ {
+ return connection.haveMinimumServerVersion("7.1");
+ }
+
+ /**
+ * In PostgreSQL, Cursors are only open within transactions.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsOpenCursorsAcrossCommit() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Do we support open cursors across multiple transactions?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsOpenCursorsAcrossRollback() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Can statements remain open across commits? They may, but
+ * this driver cannot guarentee that. In further reflection.
+ * we are talking a Statement object here, so the answer is
+ * yes, since the Statement is only a vehicle to ExecSQL()
+ *
+ * @return true if they always remain open; false otherwise
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsOpenStatementsAcrossCommit() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * Can statements remain open across rollbacks? They may, but
+ * this driver cannot guarentee that. In further contemplation,
+ * we are talking a Statement object here, so the answer is yes,
+ * since the Statement is only a vehicle to ExecSQL() in Connection
+ *
+ * @return true if they always remain open; false otherwise
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsOpenStatementsAcrossRollback() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * How many hex characters can you have in an inline binary literal
+ *
+ * @return the max literal length
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxBinaryLiteralLength() throws SQLException
+ {
+ return 0; // no limit
+ }
+
+ /**
+ * What is the maximum length for a character literal
+ * I suppose it is 8190 (8192 - 2 for the quotes)
+ *
+ * @return the max literal length
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxCharLiteralLength() throws SQLException
+ {
+ return 0; // no limit
+ }
+
+ /**
+ * Whats the limit on column name length. The description of
+ * pg_class would say '32' (length of pg_class.relname) - we
+ * should probably do a query for this....but....
+ *
+ * @return the maximum column name length
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxColumnNameLength() throws SQLException
+ {
+ return 32;
+ }
+
+ /**
+ * What is the maximum number of columns in a "GROUP BY" clause?
+ *
+ * @return the max number of columns
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxColumnsInGroupBy() throws SQLException
+ {
+ return 0; // no limit
+ }
+
+ /**
+ * What's the maximum number of columns allowed in an index?
+ * 6.0 only allowed one column, but 6.1 introduced multi-column
+ * indices, so, theoretically, its all of them.
+ *
+ * @return max number of columns
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxColumnsInIndex() throws SQLException
+ {
+ return getMaxColumnsInTable();
+ }
+
+ /**
+ * What's the maximum number of columns in an "ORDER BY clause?
+ *
+ * @return the max columns
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxColumnsInOrderBy() throws SQLException
+ {
+ return 0; // no limit
+ }
+
+ /**
+ * What is the maximum number of columns in a "SELECT" list?
+ *
+ * @return the max columns
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxColumnsInSelect() throws SQLException
+ {
+ return 0; // no limit
+ }
+
+ /**
+ * What is the maximum number of columns in a table? From the
+ * CREATE TABLE reference page...
+ *
+ * <p>"The new class is created as a heap with no initial data. A
+ * class can have no more than 1600 attributes (realistically,
+ * this is limited by the fact that tuple sizes must be less than
+ * 8192 bytes)..."
+ *
+ * @return the max columns
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxColumnsInTable() throws SQLException
+ {
+ return 1600;
+ }
+
+ /**
+ * How many active connection can we have at a time to this
+ * database? Well, since it depends on postmaster, which just
+ * does a listen() followed by an accept() and fork(), its
+ * basically very high. Unless the system runs out of processes,
+ * it can be 65535 (the number of aux. ports on a TCP/IP system).
+ * I will return 8192 since that is what even the largest system
+ * can realistically handle,
+ *
+ * @return the maximum number of connections
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxConnections() throws SQLException
+ {
+ return 8192;
+ }
+
+ /**
+ * What is the maximum cursor name length (the same as all
+ * the other F***** identifiers!)
+ *
+ * @return max cursor name length in bytes
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxCursorNameLength() throws SQLException
+ {
+ return 32;
+ }
+
+ /**
+ * Retrieves the maximum number of bytes for an index, including all
+ * of the parts of the index.
+ *
+ * @return max index length in bytes, which includes the composite
+ * of all the constituent parts of the index; a result of zero means
+ * that there is no limit or the limit is not known
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxIndexLength() throws SQLException
+ {
+ return 0; // no limit (larger than an int anyway)
+ }
+
+ public int getMaxSchemaNameLength() throws SQLException
+ {
+ // XXX-Not Implemented
+ return 0;
+ }
+
+ /**
+ * What is the maximum length of a procedure name?
+ * (length of pg_proc.proname used) - again, I really
+ * should do a query here to get it.
+ *
+ * @return the max name length in bytes
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxProcedureNameLength() throws SQLException
+ {
+ return 32;
+ }
+
+ public int getMaxCatalogNameLength() throws SQLException
+ {
+ // XXX-Not Implemented
+ return 0;
+ }
+
+ /**
+ * What is the maximum length of a single row?
+ *
+ * @return max row size in bytes
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxRowSize() throws SQLException
+ {
+ if (connection.haveMinimumServerVersion("7.1"))
+ return 1073741824; // 1 GB
+ else
+ return 8192; // XXX could be altered
+ }
+
+ /**
+ * Did getMaxRowSize() include LONGVARCHAR and LONGVARBINARY
+ * blobs? We don't handle blobs yet
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean doesMaxRowSizeIncludeBlobs() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * What is the maximum length of a SQL statement?
+ *
+ * @return max length in bytes
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxStatementLength() throws SQLException
+ {
+ if (connection.haveMinimumServerVersion("7.0"))
+ return 0; // actually whatever fits in size_t
+ else
+ return 16384;
+ }
+
+ /**
+ * How many active statements can we have open at one time to
+ * this database? Basically, since each Statement downloads
+ * the results as the query is executed, we can have many. However,
+ * we can only really have one statement per connection going
+ * at once (since they are executed serially) - so we return
+ * one.
+ *
+ * @return the maximum
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxStatements() throws SQLException
+ {
+ return 1;
+ }
+
+ /**
+ * What is the maximum length of a table name? This was found
+ * from pg_class.relname length
+ *
+ * @return max name length in bytes
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxTableNameLength() throws SQLException
+ {
+ return 32;
+ }
+
+ /**
+ * What is the maximum number of tables that can be specified
+ * in a SELECT?
+ *
+ * @return the maximum
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxTablesInSelect() throws SQLException
+ {
+ return 0; // no limit
+ }
+
+ /**
+ * What is the maximum length of a user name? Well, we generally
+ * use UNIX like user names in PostgreSQL, so I think this would
+ * be 8. However, showing the schema for pg_user shows a length
+ * for username of 32.
+ *
+ * @return the max name length in bytes
+ * @exception SQLException if a database access error occurs
+ */
+ public int getMaxUserNameLength() throws SQLException
+ {
+ return 32;
+ }
+
+
+ /**
+ * What is the database's default transaction isolation level? We
+ * do not support this, so all transactions are SERIALIZABLE.
+ *
+ * @return the default isolation level
+ * @exception SQLException if a database access error occurs
+ * @see Connection
+ */
+ public int getDefaultTransactionIsolation() throws SQLException
+ {
+ return Connection.TRANSACTION_READ_COMMITTED;
+ }
+
+ /**
+ * Are transactions supported? If not, commit and rollback are noops
+ * and the isolation level is TRANSACTION_NONE. We do support
+ * transactions.
+ *
+ * @return true if transactions are supported
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsTransactions() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * Does the database support the given transaction isolation level?
+ * We only support TRANSACTION_SERIALIZABLE and TRANSACTION_READ_COMMITTED
+ *
+ * @param level the values are defined in java.sql.Connection
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ * @see Connection
+ */
+ public boolean supportsTransactionIsolationLevel(int level) throws SQLException
+ {
+ if (level == Connection.TRANSACTION_SERIALIZABLE ||
+ level == Connection.TRANSACTION_READ_COMMITTED)
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * Are both data definition and data manipulation transactions
+ * supported?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * Are only data manipulation statements withing a transaction
+ * supported?
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsDataManipulationTransactionsOnly() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Does a data definition statement within a transaction force
+ * the transaction to commit? I think this means something like:
+ *
+ * <p><pre>
+ * CREATE TABLE T (A INT);
+ * INSERT INTO T (A) VALUES (2);
+ * BEGIN;
+ * UPDATE T SET A = A + 1;
+ * CREATE TABLE X (A INT);
+ * SELECT A FROM T INTO X;
+ * COMMIT;
+ * </pre><p>
+ *
+ * does the CREATE TABLE call cause a commit? The answer is no.
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean dataDefinitionCausesTransactionCommit() throws SQLException
+ {
+ return false;
+ }
+
+ /**
+ * Is a data definition statement within a transaction ignored?
+ * It seems to be (from experiment in previous method)
+ *
+ * @return true if so
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean dataDefinitionIgnoredInTransactions() throws SQLException
+ {
+ return true;
+ }
+
+ /**
+ * Get a description of stored procedures available in a catalog
+ *
+ * <p>Only procedure descriptions matching the schema and procedure
+ * name criteria are returned. They are ordered by PROCEDURE_SCHEM
+ * and PROCEDURE_NAME
+ *
+ * <p>Each procedure description has the following columns:
+ * <ol>
+ * <li><b>PROCEDURE_CAT</b> String => procedure catalog (may be null)
+ * <li><b>PROCEDURE_SCHEM</b> String => procedure schema (may be null)
+ * <li><b>PROCEDURE_NAME</b> String => procedure name
+ * <li><b>Field 4</b> reserved (make it null)
+ * <li><b>Field 5</b> reserved (make it null)
+ * <li><b>Field 6</b> reserved (make it null)
+ * <li><b>REMARKS</b> String => explanatory comment on the procedure
+ * <li><b>PROCEDURE_TYPE</b> short => kind of procedure
+ * <ul>
+ * <li> procedureResultUnknown - May return a result
+ * <li> procedureNoResult - Does not return a result
+ * <li> procedureReturnsResult - Returns a result
+ * </ul>
+ * </ol>
+ *
+ * @param catalog - a catalog name; "" retrieves those without a
+ * catalog; null means drop catalog name from criteria
+ * @param schemaParrern - a schema name pattern; "" retrieves those
+ * without a schema - we ignore this parameter
+ * @param procedureNamePattern - a procedure name pattern
+ * @return ResultSet - each row is a procedure description
+ * @exception SQLException if a database access error occurs
+ */
+ public java.sql.ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException
+ {
+ // the field descriptors for the new ResultSet
+ Field f[] = new Field[8];
+ java.sql.ResultSet r; // ResultSet for the SQL query that we need to do
+ Vector v = new Vector(); // The new ResultSet tuple stuff
+
+ f[0] = new Field(connection, "PROCEDURE_CAT", iVarcharOid, 32);
+ f[1] = new Field(connection, "PROCEDURE_SCHEM", iVarcharOid, 32);
+ f[2] = new Field(connection, "PROCEDURE_NAME", iVarcharOid, 32);
+ f[3] = f[4] = f[5] = new Field(connection, "reserved", iVarcharOid, 32); // null; // reserved, must be null for now
+ f[6] = new Field(connection, "REMARKS", iVarcharOid, 8192);
+ f[7] = new Field(connection, "PROCEDURE_TYPE", iInt2Oid, 2);
+
+ // If the pattern is null, then set it to the default
+ if (procedureNamePattern == null)
+ procedureNamePattern = "%";
+
+ r = connection.ExecSQL("select proname, proretset from pg_proc where proname like '" + procedureNamePattern.toLowerCase() + "' order by proname");
+
+ while (r.next())
+ {
+ byte[][] tuple = new byte[8][0];
+
+ tuple[0] = null; // Catalog name
+ tuple[1] = null; // Schema name
+ tuple[2] = r.getBytes(1); // Procedure name
+ tuple[3] = tuple[4] = tuple[5] = null; // Reserved
+ tuple[6] = null; // Remarks
+
+ if (r.getBoolean(2))
+ tuple[7] = Integer.toString(java.sql.DatabaseMetaData.procedureReturnsResult).getBytes();
+ else
+ tuple[7] = Integer.toString(java.sql.DatabaseMetaData.procedureNoResult).getBytes();
+
+ v.addElement(tuple);
+ }
+ return new ResultSet(connection, f, v, "OK", 1);
+ }
+
+ /**
+ * Get a description of a catalog's stored procedure parameters
+ * and result columns.
+ *
+ * <p>Only descriptions matching the schema, procedure and parameter
+ * name criteria are returned. They are ordered by PROCEDURE_SCHEM
+ * and PROCEDURE_NAME. Within this, the return value, if any, is
+ * first. Next are the parameter descriptions in call order. The
+ * column descriptions follow in column number order.
+ *
+ * <p>Each row in the ResultSet is a parameter description or column
+ * description with the following fields:
+ * <ol>
+ * <li><b>PROCEDURE_CAT</b> String => procedure catalog (may be null)
+ * <li><b>PROCEDURE_SCHE</b>M String => procedure schema (may be null)
+ * <li><b>PROCEDURE_NAME</b> String => procedure name
+ * <li><b>COLUMN_NAME</b> String => column/parameter name
+ * <li><b>COLUMN_TYPE</b> Short => kind of column/parameter:
+ * <ul><li>procedureColumnUnknown - nobody knows
+ * <li>procedureColumnIn - IN parameter
+ * <li>procedureColumnInOut - INOUT parameter
+ * <li>procedureColumnOut - OUT parameter
+ * <li>procedureColumnReturn - procedure return value
+ * <li>procedureColumnResult - result column in ResultSet
+ * </ul>
+ * <li><b>DATA_TYPE</b> short => SQL type from java.sql.Types
+ * <li><b>TYPE_NAME</b> String => SQL type name
+ * <li><b>PRECISION</b> int => precision
+ * <li><b>LENGTH</b> int => length in bytes of data
+ * <li><b>SCALE</b> short => scale
+ * <li><b>RADIX</b> short => radix
+ * <li><b>NULLABLE</b> short => can it contain NULL?
+ * <ul><li>procedureNoNulls - does not allow NULL values
+ * <li>procedureNullable - allows NULL values
+ * <li>procedureNullableUnknown - nullability unknown
+ * <li><b>REMARKS</b> String => comment describing parameter/column
+ * </ol>
+ * @param catalog This is ignored in org.postgresql, advise this is set to null
+ * @param schemaPattern This is ignored in org.postgresql, advise this is set to null
+ * @param procedureNamePattern a procedure name pattern
+ * @param columnNamePattern a column name pattern
+ * @return each row is a stored procedure parameter or column description
+ * @exception SQLException if a database-access error occurs
+ * @see #getSearchStringEscape
+ */
+ // Implementation note: This is required for Borland's JBuilder to work
+ public java.sql.ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException
+ {
+ if (procedureNamePattern == null)
+ procedureNamePattern = "%";
+
+ if (columnNamePattern == null)
+ columnNamePattern = "%";
+
+ // for now, this returns an empty result set.
+ Field f[] = new Field[13];
+ ResultSet r; // ResultSet for the SQL query that we need to do
+ Vector v = new Vector(); // The new ResultSet tuple stuff
+
+ f[0] = new Field(connection, "PROCEDURE_CAT", iVarcharOid, 32);
+ f[1] = new Field(connection, "PROCEDURE_SCHEM", iVarcharOid, 32);
+ f[2] = new Field(connection, "PROCEDURE_NAME", iVarcharOid, 32);
+ f[3] = new Field(connection, "COLUMN_NAME", iVarcharOid, 32);
+ f[4] = new Field(connection, "COLUMN_TYPE", iInt2Oid, 2);
+ f[5] = new Field(connection, "DATA_TYPE", iInt2Oid, 2);
+ f[6] = new Field(connection, "TYPE_NAME", iVarcharOid, 32);
+ f[7] = new Field(connection, "PRECISION", iInt4Oid, 4);
+ f[8] = new Field(connection, "LENGTH", iInt4Oid, 4);
+ f[9] = new Field(connection, "SCALE", iInt2Oid, 2);
+ f[10] = new Field(connection, "RADIX", iInt2Oid, 2);
+ f[11] = new Field(connection, "NULLABLE", iInt2Oid, 2);
+ f[12] = new Field(connection, "REMARKS", iVarcharOid, 32);
+
+ // add query loop here
+
+ return new ResultSet(connection, f, v, "OK", 1);
+ }
+
+ /**
+ * Get a description of tables available in a catalog.
+ *
+ * <p>Only table descriptions matching the catalog, schema, table
+ * name and type criteria are returned. They are ordered by
+ * TABLE_TYPE, TABLE_SCHEM and TABLE_NAME.
+ *
+ * <p>Each table description has the following columns:
+ *
+ * <ol>
+ * <li><b>TABLE_CAT</b> String => table catalog (may be null)
+ * <li><b>TABLE_SCHEM</b> String => table schema (may be null)
+ * <li><b>TABLE_NAME</b> String => table name
+ * <li><b>TABLE_TYPE</b> String => table type. Typical types are "TABLE",
+ * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL
+ * TEMPORARY", "ALIAS", "SYNONYM".
+ * <li><b>REMARKS</b> String => explanatory comment on the table
+ * </ol>
+ *
+ * <p>The valid values for the types parameter are:
+ * "TABLE", "INDEX", "SEQUENCE", "SYSTEM TABLE" and "SYSTEM INDEX"
+ *
+ * @param catalog a catalog name; For org.postgresql, this is ignored, and
+ * should be set to null
+ * @param schemaPattern a schema name pattern; For org.postgresql, this is ignored, and
+ * should be set to null
+ * @param tableNamePattern a table name pattern. For all tables this should be "%"
+ * @param types a list of table types to include; null returns
+ * all types
+ * @return each row is a table description
+ * @exception SQLException if a database-access error occurs.
+ */
+ public java.sql.ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String types[]) throws SQLException
+ {
+ // Handle default value for types
+ if (types == null)
+ types = defaultTableTypes;
+
+ if (tableNamePattern == null)
+ tableNamePattern = "%";
+
+ // the field descriptors for the new ResultSet
+ Field f[] = new Field[5];
+ java.sql.ResultSet r; // ResultSet for the SQL query that we need to do
+ Vector v = new Vector(); // The new ResultSet tuple stuff
+
+ f[0] = new Field(connection, "TABLE_CAT", iVarcharOid, 32);
+ f[1] = new Field(connection, "TABLE_SCHEM", iVarcharOid, 32);
+ f[2] = new Field(connection, "TABLE_NAME", iVarcharOid, 32);
+ f[3] = new Field(connection, "TABLE_TYPE", iVarcharOid, 32);
+ f[4] = new Field(connection, "REMARKS", iVarcharOid, 32);
+
+ // Now form the query
+ StringBuffer sql = new StringBuffer("select relname,oid,relkind from pg_class where (");
+
+ boolean notFirst = false;
+ for (int i = 0;i < types.length;i++)
+ {
+ for (int j = 0;j < getTableTypes.length;j++)
+ if (getTableTypes[j][0].equals(types[i]))
+ {
+ if (notFirst)
+ sql.append(" or ");
+ sql.append(getTableTypes[j][1]);
+ notFirst = true;
+ }
+ }
+
+ // Added by Stefan Andreasen <stefan@linux.kapow.dk>
+ // Now take the pattern into account
+ sql.append(") and relname like '");
+ sql.append(tableNamePattern.toLowerCase());
+ sql.append("' order by relkind, relname");
+
+ // Now run the query
+ r = connection.ExecSQL(sql.toString());
+
+ while (r.next())
+ {
+ byte[][] tuple = new byte[5][0];
+
+ // Fetch the description for the table (if any)
+ String getDescriptionStatement =
+ connection.haveMinimumServerVersion("7.2") ?
+ "select obj_description(" + r.getInt(2) + ",'pg_class')" :
+ "select description from pg_description where objoid=" + r.getInt(2);
+
+ java.sql.ResultSet dr = connection.ExecSQL(getDescriptionStatement);
+
+ byte remarks[] = null;
+
+ if (((org.postgresql.ResultSet)dr).getTupleCount() == 1)
+ {
+ dr.next();
+ remarks = dr.getBytes(1);
+ }
+ dr.close();
+
+ String relKind;
+ switch (r.getBytes(3)[0])
+ {
+ case (byte) 'r':
+ relKind = "TABLE";
+ break;
+ case (byte) 'i':
+ relKind = "INDEX";
+ break;
+ case (byte) 'S':
+ relKind = "SEQUENCE";
+ break;
+ case (byte) 'v':
+ relKind = "VIEW";
+ break;
+ default:
+ relKind = null;
+ }
+
+ tuple[0] = null; // Catalog name
+ tuple[1] = null; // Schema name
+ tuple[2] = r.getBytes(1); // Table name
+ tuple[3] = (relKind == null) ? null : relKind.getBytes(); // Table type
+ tuple[4] = remarks; // Remarks
+ v.addElement(tuple);
+ }
+ r.close();
+ return new ResultSet(connection, f, v, "OK", 1);
+ }
+
+ // This array contains the valid values for the types argument
+ // in getTables().
+ //
+ // Each supported type consists of it's name, and the sql where
+ // clause to retrieve that value.
+ //
+ // IMPORTANT: the query must be enclosed in ( )
+ private static final String getTableTypes[][] = {
+ {"TABLE", "(relkind='r' and relhasrules='f' and relname !~ '^pg_' and relname !~ '^xinv')"},
+ {"VIEW", "(relkind='v' and relname !~ '^pg_')"},
+ {"INDEX", "(relkind='i' and relname !~ '^pg_')"},
+ {"SEQUENCE", "(relkind='S' and relname !~ '^pg_')"},
+ {"SYSTEM TABLE", "(relkind='r' and relname ~ '^pg_')"},
+ {"SYSTEM INDEX", "(relkind='i' and relname ~ '^pg_')"}
+ };
+
+ // These are the default tables, used when NULL is passed to getTables
+ // The choice of these provide the same behaviour as psql's \d
+ private static final String defaultTableTypes[] = {
+ "TABLE", "VIEW", "INDEX", "SEQUENCE"
+ };
+
+ /**
+ * Get the schema names available in this database. The results
+ * are ordered by schema name.
+ *
+ * <P>The schema column is:
+ * <OL>
+ * <LI><B>TABLE_SCHEM</B> String => schema name
+ * </OL>
+ *
+ * @return ResultSet each row has a single String column that is a
+ * schema name
+ */
+ public java.sql.ResultSet getSchemas() throws SQLException
+ {
+ // We don't use schemas, so we simply return a single schema name "".
+ //
+ Field f[] = new Field[1];
+ Vector v = new Vector();
+ byte[][] tuple = new byte[1][0];
+ f[0] = new Field(connection, "TABLE_SCHEM", iVarcharOid, 32);
+ tuple[0] = "".getBytes();
+ v.addElement(tuple);
+ return new ResultSet(connection, f, v, "OK", 1);
+ }
+
+ /**
+ * Get the catalog names available in this database. The results
+ * are ordered by catalog name.
+ *
+ * <P>The catalog column is:
+ * <OL>
+ * <LI><B>TABLE_CAT</B> String => catalog name
+ * </OL>
+ *
+ * @return ResultSet each row has a single String column that is a
+ * catalog name
+ */
+ public java.sql.ResultSet getCatalogs() throws SQLException
+ {
+ return connection.createStatement().executeQuery("select datname as TABLE_CAT from pg_database;");
+ }
+
+ /**
+ * Get the table types available in this database. The results
+ * are ordered by table type.
+ *
+ * <P>The table type is:
+ * <OL>
+ * <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
+ * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
+ * "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
+ * </OL>
+ *
+ * @return ResultSet each row has a single String column that is a
+ * table type
+ */
+ public java.sql.ResultSet getTableTypes() throws SQLException
+ {
+ Field f[] = new Field[1];
+ Vector v = new Vector();
+ f[0] = new Field(connection, new String("TABLE_TYPE"), iVarcharOid, 32);
+ for (int i = 0;i < getTableTypes.length;i++)
+ {
+ byte[][] tuple = new byte[1][0];
+ tuple[0] = getTableTypes[i][0].getBytes();
+ v.addElement(tuple);
+ }
+ return new ResultSet(connection, f, v, "OK", 1);
+ }
+
+ /**
+ * Get a description of table columns available in a catalog.
+ *
+ * <P>Only column descriptions matching the catalog, schema, table
+ * and column name criteria are returned. They are ordered by
+ * TABLE_SCHEM, TABLE_NAME and ORDINAL_POSITION.
+ *
+ * <P>Each column description has the following columns:
+ * <OL>
+ * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
+ * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
+ * <LI><B>TABLE_NAME</B> String => table name
+ * <LI><B>COLUMN_NAME</B> String => column name
+ * <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
+ * <LI><B>TYPE_NAME</B> String => Data source dependent type name
+ * <LI><B>COLUMN_SIZE</B> int => column size. For char or date
+ * types this is the maximum number of characters, for numeric or
+ * decimal types this is precision.
+ * <LI><B>BUFFER_LENGTH</B> is not used.
+ * <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits
+ * <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
+ * <LI><B>NULLABLE</B> int => is NULL allowed?
+ * <UL>
+ * <LI> columnNoNulls - might not allow NULL values
+ * <LI> columnNullable - definitely allows NULL values
+ * <LI> columnNullableUnknown - nullability unknown
+ * </UL>
+ * <LI><B>REMARKS</B> String => comment describing column (may be null)
+ * <LI><B>COLUMN_DEF</B> String => default value (may be null)
+ * <LI><B>SQL_DATA_TYPE</B> int => unused
+ * <LI><B>SQL_DATETIME_SUB</B> int => unused
+ * <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
+ * maximum number of bytes in the column
+ * <LI><B>ORDINAL_POSITION</B> int => index of column in table
+ * (starting at 1)
+ * <LI><B>IS_NULLABLE</B> String => "NO" means column definitely
+ * does not allow NULL values; "YES" means the column might
+ * allow NULL values. An empty string means nobody knows.
+ * </OL>
+ *
+ * @param catalog a catalog name; "" retrieves those without a catalog
+ * @param schemaPattern a schema name pattern; "" retrieves those
+ * without a schema
+ * @param tableNamePattern a table name pattern
+ * @param columnNamePattern a column name pattern
+ * @return ResultSet each row is a column description
+ * @see #getSearchStringEscape
+ */
+ public java.sql.ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException
+ {
+ Vector v = new Vector(); // The new ResultSet tuple stuff
+ Field f[] = new Field[18]; // The field descriptors for the new ResultSet
+
+ f[0] = new Field(connection, "TABLE_CAT", iVarcharOid, 32);
+ f[1] = new Field(connection, "TABLE_SCHEM", iVarcharOid, 32);
+ f[2] = new Field(connection, "TABLE_NAME", iVarcharOid, 32);
+ f[3] = new Field(connection, "COLUMN_NAME", iVarcharOid, 32);
+ f[4] = new Field(connection, "DATA_TYPE", iInt2Oid, 2);
+ f[5] = new Field(connection, "TYPE_NAME", iVarcharOid, 32);
+ f[6] = new Field(connection, "COLUMN_SIZE", iInt4Oid, 4);
+ f[7] = new Field(connection, "BUFFER_LENGTH", iVarcharOid, 32);
+ f[8] = new Field(connection, "DECIMAL_DIGITS", iInt4Oid, 4);
+ f[9] = new Field(connection, "NUM_PREC_RADIX", iInt4Oid, 4);
+ f[10] = new Field(connection, "NULLABLE", iInt4Oid, 4);
+ f[11] = new Field(connection, "REMARKS", iVarcharOid, 32);
+ f[12] = new Field(connection, "COLUMN_DEF", iVarcharOid, 32);
+ f[13] = new Field(connection, "SQL_DATA_TYPE", iInt4Oid, 4);
+ f[14] = new Field(connection, "SQL_DATETIME_SUB", iInt4Oid, 4);
+ f[15] = new Field(connection, "CHAR_OCTET_LENGTH", iVarcharOid, 32);
+ f[16] = new Field(connection, "ORDINAL_POSITION", iInt4Oid, 4);
+ f[17] = new Field(connection, "IS_NULLABLE", iVarcharOid, 32);
+
+ StringBuffer sql = new StringBuffer(512);
+
+ /* Build a >= 7.1 SQL statement to list all columns */
+ sql.append("select " +
+ (connection.haveMinimumServerVersion("7.2") ? "a.attrelid, " : "a.oid, ") +
+ " c.relname, " +
+ " a.attname, " +
+ " a.atttypid, " +
+ " a.attnum, " +
+ " a.attnotnull, " +
+ " a.attlen, " +
+ " a.atttypmod, " +
+ " d.adsrc, " +
+ " t.typname, " +
+ /* Use the new col_description in 7.2 or an additional outer join in 7.1 */
+ (connection.haveMinimumServerVersion("7.2") ? "col_description(a.attrelid, a.attnum) " : "e.description ") +
+ "from" +
+ " (" +
+ " (pg_class c inner join pg_attribute a on" +
+ " (" +
+ " a.attrelid=c.oid");
+
+ if ((tableNamePattern != null) && ! tableNamePattern.equals("%"))
+ {
+ sql.append(" and c.relname like \'" + tableNamePattern + "\'");
+ }
+
+ if ((columnNamePattern != null) && ! columnNamePattern.equals("%"))
+ {
+ sql.append(" and a.attname like \'" + columnNamePattern + "\'");
+ }
+
sql.append(
- " left outer join pg_description e on" +
+ " and a.attnum > 0" +
+ " )" +
+ " ) inner join pg_type t on" +
+ " (" +
+ " t.oid = a.atttypid" +
+ " )" +
+ " )" +
+ " left outer join pg_attrdef d on" +
" (" +
- " e.objoid = a.oid" +
+ " c.oid = d.adrelid" +
+ " and a.attnum = d.adnum" +
" ) ");
+
+ if (!connection.haveMinimumServerVersion("7.2"))
+ {
+ /* Only for 7.1 */
+ sql.append(
+ " left outer join pg_description e on" +
+ " (" +
+ " e.objoid = a.oid" +
+ " ) ");
+ }
+
+ sql.append("order by" +
+ " c.relname, a.attnum");
+
+ java.sql.ResultSet r = connection.ExecSQL(sql.toString());
+ while (r.next())
+ {
+ byte[][] tuple = new byte[18][0];
+
+ String nullFlag = r.getString(6);
+ String typname = r.getString(10);
+
+ tuple[0] = null; // Catalog name, not supported
+ tuple[1] = null; // Schema name, not supported
+ tuple[2] = r.getBytes(2); // Table name
+ tuple[3] = r.getBytes(3); // Column name
+ tuple[4] = Integer.toString(connection.getSQLType(typname)).getBytes(); // Data type
+ tuple[5] = typname.getBytes(); // Type name
+
+ // Column size
+ // Looking at the psql source,
+ // I think the length of a varchar as specified when the table was created
+ // should be extracted from atttypmod which contains this length + sizeof(int32)
+ if (typname.equals("bpchar") || typname.equals("varchar"))
+ {
+ int atttypmod = r.getInt(8);
+ tuple[6] = Integer.toString(atttypmod != -1 ? atttypmod - VARHDRSZ : 0).getBytes();
+ }
+ else
+ {
+ tuple[6] = r.getBytes(7);
+ }
+
+ tuple[7] = null; // Buffer length
+ tuple[8] = "0".getBytes(); // Decimal Digits - how to get this?
+ tuple[9] = "10".getBytes(); // Num Prec Radix - assume decimal
+ tuple[10] = Integer.toString(nullFlag.equals("f") ?
+ java.sql.DatabaseMetaData.columnNullable :
+ java.sql.DatabaseMetaData.columnNoNulls).getBytes(); // Nullable
+ tuple[11] = r.getBytes(11); // Description (if any)
+ tuple[12] = r.getBytes(9); // Column default
+ tuple[13] = null; // sql data type (unused)
+ tuple[14] = null; // sql datetime sub (unused)
+ tuple[15] = tuple[6]; // char octet length
+ tuple[16] = r.getBytes(5); // ordinal position
+ tuple[17] = (nullFlag.equals("f") ? "YES" : "NO").getBytes(); // Is nullable
+
+ v.addElement(tuple);
+ }
+ r.close();
+
+ return new ResultSet(connection, f, v, "OK", 1);
}
- sql.append("order by" +
- " c.relname, a.attnum");
-
- java.sql.ResultSet r = connection.ExecSQL(sql.toString());
- while (r.next()) {
- byte[][] tuple = new byte[18][0];
-
- String nullFlag = r.getString(6);
- String typname = r.getString(10);
-
- tuple[0] = null; // Catalog name, not supported
- tuple[1] = null; // Schema name, not supported
- tuple[2] = r.getBytes(2); // Table name
- tuple[3] = r.getBytes(3); // Column name
- tuple[4] = Integer.toString(connection.getSQLType(typname)).getBytes(); // Data type
- tuple[5] = typname.getBytes(); // Type name
-
- // Column size
- // Looking at the psql source,
- // I think the length of a varchar as specified when the table was created
- // should be extracted from atttypmod which contains this length + sizeof(int32)
- if (typname.equals("bpchar") || typname.equals("varchar")) {
- int atttypmod = r.getInt(8);
- tuple[6] = Integer.toString(atttypmod != -1 ? atttypmod - VARHDRSZ : 0).getBytes();
- } else {
- tuple[6] = r.getBytes(7);
+ /**
+ * Get a description of the access rights for a table's columns.
+ *
+ * <P>Only privileges matching the column name criteria are
+ * returned. They are ordered by COLUMN_NAME and PRIVILEGE.
+ *
+ * <P>Each privilige description has the following columns:
+ * <OL>
+ * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
+ * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
+ * <LI><B>TABLE_NAME</B> String => table name
+ * <LI><B>COLUMN_NAME</B> String => column name
+ * <LI><B>GRANTOR</B> => grantor of access (may be null)
+ * <LI><B>GRANTEE</B> String => grantee of access
+ * <LI><B>PRIVILEGE</B> String => name of access (SELECT,
+ * INSERT, UPDATE, REFRENCES, ...)
+ * <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
+ * to grant to others; "NO" if not; null if unknown
+ * </OL>
+ *
+ * @param catalog a catalog name; "" retrieves those without a catalog
+ * @param schema a schema name; "" retrieves those without a schema
+ * @param table a table name
+ * @param columnNamePattern a column name pattern
+ * @return ResultSet each row is a column privilege description
+ * @see #getSearchStringEscape
+ */
+ public java.sql.ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException
+ {
+ Field f[] = new Field[8];
+ Vector v = new Vector();
+
+ if (table == null)
+ table = "%";
+
+ if (columnNamePattern == null)
+ columnNamePattern = "%";
+ else
+ columnNamePattern = columnNamePattern.toLowerCase();
+
+ f[0] = new Field(connection, "TABLE_CAT", iVarcharOid, 32);
+ f[1] = new Field(connection, "TABLE_SCHEM", iVarcharOid, 32);
+ f[2] = new Field(connection, "TABLE_NAME", iVarcharOid, 32);
+ f[3] = new Field(connection, "COLUMN_NAME", iVarcharOid, 32);
+ f[4] = new Field(connection, "GRANTOR", iVarcharOid, 32);
+ f[5] = new Field(connection, "GRANTEE", iVarcharOid, 32);
+ f[6] = new Field(connection, "PRIVILEGE", iVarcharOid, 32);
+ f[7] = new Field(connection, "IS_GRANTABLE", iVarcharOid, 32);
+
+ // This is taken direct from the psql source
+ java.sql.ResultSet r = connection.ExecSQL("SELECT relname, relacl FROM pg_class, pg_user WHERE ( relkind = 'r' OR relkind = 'i') and relname !~ '^pg_' and relname !~ '^xin[vx][0-9]+' and usesysid = relowner and relname like '" + table.toLowerCase() + "' ORDER BY relname");
+ while (r.next())
+ {
+ byte[][] tuple = new byte[8][0];
+ tuple[0] = tuple[1] = "".getBytes();
+ DriverManager.println("relname=\"" + r.getString(1) + "\" relacl=\"" + r.getString(2) + "\"");
+
+ // For now, don't add to the result as relacl needs to be processed.
+ //v.addElement(tuple);
}
- tuple[7] = null; // Buffer length
- tuple[8] = "0".getBytes(); // Decimal Digits - how to get this?
- tuple[9] = "10".getBytes(); // Num Prec Radix - assume decimal
- tuple[10] = Integer.toString(nullFlag.equals("f") ?
- java.sql.DatabaseMetaData.columnNullable :
- java.sql.DatabaseMetaData.columnNoNulls).getBytes(); // Nullable
- tuple[11] = r.getBytes(11); // Description (if any)
- tuple[12] = r.getBytes(9); // Column default
- tuple[13] = null; // sql data type (unused)
- tuple[14] = null; // sql datetime sub (unused)
- tuple[15] = tuple[6]; // char octet length
- tuple[16] = r.getBytes(5); // ordinal position
- tuple[17] = (nullFlag.equals("f") ? "YES" : "NO").getBytes(); // Is nullable
+ return new ResultSet(connection, f, v, "OK", 1);
+ }
- v.addElement(tuple);
+ /**
+ * Get a description of the access rights for each table available
+ * in a catalog.
+ *
+ * This method is currently unimplemented.
+ *
+ * <P>Only privileges matching the schema and table name
+ * criteria are returned. They are ordered by TABLE_SCHEM,
+ * TABLE_NAME, and PRIVILEGE.
+ *
+ * <P>Each privilige description has the following columns:
+ * <OL>
+ * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
+ * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
+ * <LI><B>TABLE_NAME</B> String => table name
+ * <LI><B>COLUMN_NAME</B> String => column name
+ * <LI><B>GRANTOR</B> => grantor of access (may be null)
+ * <LI><B>GRANTEE</B> String => grantee of access
+ * <LI><B>PRIVILEGE</B> String => name of access (SELECT,
+ * INSERT, UPDATE, REFRENCES, ...)
+ * <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
+ * to grant to others; "NO" if not; null if unknown
+ * </OL>
+ *
+ * @param catalog a catalog name; "" retrieves those without a catalog
+ * @param schemaPattern a schema name pattern; "" retrieves those
+ * without a schema
+ * @param tableNamePattern a table name pattern
+ * @return ResultSet each row is a table privilege description
+ * @see #getSearchStringEscape
+ */
+ public java.sql.ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented();
+ }
+
+ /**
+ * Get a description of a table's optimal set of columns that
+ * uniquely identifies a row. They are ordered by SCOPE.
+ *
+ * <P>Each column description has the following columns:
+ * <OL>
+ * <LI><B>SCOPE</B> short => actual scope of result
+ * <UL>
+ * <LI> bestRowTemporary - very temporary, while using row
+ * <LI> bestRowTransaction - valid for remainder of current transaction
+ * <LI> bestRowSession - valid for remainder of current session
+ * </UL>
+ * <LI><B>COLUMN_NAME</B> String => column name
+ * <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
+ * <LI><B>TYPE_NAME</B> String => Data source dependent type name
+ * <LI><B>COLUMN_SIZE</B> int => precision
+ * <LI><B>BUFFER_LENGTH</B> int => not used
+ * <LI><B>DECIMAL_DIGITS</B> short => scale
+ * <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
+ * like an Oracle ROWID
+ * <UL>
+ * <LI> bestRowUnknown - may or may not be pseudo column
+ * <LI> bestRowNotPseudo - is NOT a pseudo column
+ * <LI> bestRowPseudo - is a pseudo column
+ * </UL>
+ * </OL>
+ *
+ * @param catalog a catalog name; "" retrieves those without a catalog
+ * @param schema a schema name; "" retrieves those without a schema
+ * @param table a table name
+ * @param scope the scope of interest; use same values as SCOPE
+ * @param nullable include columns that are nullable?
+ * @return ResultSet each row is a column description
+ */
+ // Implementation note: This is required for Borland's JBuilder to work
+ public java.sql.ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException
+ {
+ // for now, this returns an empty result set.
+ Field f[] = new Field[8];
+ ResultSet r; // ResultSet for the SQL query that we need to do
+ Vector v = new Vector(); // The new ResultSet tuple stuff
+
+ f[0] = new Field(connection, "SCOPE", iInt2Oid, 2);
+ f[1] = new Field(connection, "COLUMN_NAME", iVarcharOid, 32);
+ f[2] = new Field(connection, "DATA_TYPE", iInt2Oid, 2);
+ f[3] = new Field(connection, "TYPE_NAME", iVarcharOid, 32);
+ f[4] = new Field(connection, "COLUMN_SIZE", iInt4Oid, 4);
+ f[5] = new Field(connection, "BUFFER_LENGTH", iInt4Oid, 4);
+ f[6] = new Field(connection, "DECIMAL_DIGITS", iInt2Oid, 2);
+ f[7] = new Field(connection, "PSEUDO_COLUMN", iInt2Oid, 2);
+
+ return new ResultSet(connection, f, v, "OK", 1);
+ }
+
+ /**
+ * Get a description of a table's columns that are automatically
+ * updated when any value in a row is updated. They are
+ * unordered.
+ *
+ * This method is currently unimplemented.
+ *
+ * <P>Each column description has the following columns:
+ * <OL>
+ * <LI><B>SCOPE</B> short => is not used
+ * <LI><B>COLUMN_NAME</B> String => column name
+ * <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
+ * <LI><B>TYPE_NAME</B> String => Data source dependent type name
+ * <LI><B>COLUMN_SIZE</B> int => precision
+ * <LI><B>BUFFER_LENGTH</B> int => length of column value in bytes
+ * <LI><B>DECIMAL_DIGITS</B> short => scale
+ * <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
+ * like an Oracle ROWID
+ * <UL>
+ * <LI> versionColumnUnknown - may or may not be pseudo column
+ * <LI> versionColumnNotPseudo - is NOT a pseudo column
+ * <LI> versionColumnPseudo - is a pseudo column
+ * </UL>
+ * </OL>
+ *
+ * @param catalog a catalog name; "" retrieves those without a catalog
+ * @param schema a schema name; "" retrieves those without a schema
+ * @param table a table name
+ * @return ResultSet each row is a column description
+ */
+ public java.sql.ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented();
+ }
+
+ /**
+ * Get a description of a table's primary key columns. They
+ * are ordered by COLUMN_NAME.
+ *
+ * <P>Each column description has the following columns:
+ * <OL>
+ * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
+ * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
+ * <LI><B>TABLE_NAME</B> String => table name
+ * <LI><B>COLUMN_NAME</B> String => column name
+ * <LI><B>KEY_SEQ</B> short => sequence number within primary key
+ * <LI><B>PK_NAME</B> String => primary key name (may be null)
+ * </OL>
+ *
+ * @param catalog a catalog name; "" retrieves those without a catalog
+ * @param schema a schema name pattern; "" retrieves those
+ * without a schema
+ * @param table a table name
+ * @return ResultSet each row is a primary key column description
+ */
+ public java.sql.ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException
+ {
+ return connection.createStatement().executeQuery("SELECT " +
+ "'' as TABLE_CAT," +
+ "'' AS TABLE_SCHEM," +
+ "bc.relname AS TABLE_NAME," +
+ "a.attname AS COLUMN_NAME," +
+ "a.attnum as KEY_SEQ," +
+ "ic.relname as PK_NAME " +
+ " FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a" +
+ " WHERE bc.relkind = 'r' " + // -- not indices
+ " and upper(bc.relname) = upper('" + table + "')" +
+ " and i.indrelid = bc.oid" +
+ " and i.indexrelid = ic.oid" +
+ " and ic.oid = a.attrelid" +
+ " and i.indisprimary='t' " +
+ " ORDER BY table_name, pk_name, key_seq"
+ );
+ }
+
+ private void importLoop(Vector tuples, java.sql.ResultSet keyRelation) throws SQLException
+ {
+ String s, s2;
+ String origTable = null, primTable = new String(""), schema;
+ int i;
+ Vector v = new Vector();
+
+ s = keyRelation.getString(1);
+ s2 = s;
+ //System.out.println(s);
+
+ for (i = 0;;i++)
+ {
+ s = s.substring(s.indexOf("\\000") + 4);
+ if (s.compareTo("") == 0)
+ {
+ //System.out.println();
+ break;
+ }
+ s2 = s.substring(0, s.indexOf("\\000"));
+ switch (i)
+ {
+ case 0:
+ origTable = s2;
+ break;
+ case 1:
+ primTable = s2;
+ break;
+ case 2:
+ schema = s2;
+ break;
+ default:
+ v.addElement(s2);
+ }
+ }
+
+ java.sql.ResultSet rstmp = connection.ExecSQL("select * from " + origTable + " where 1=0");
+ java.sql.ResultSetMetaData origCols = rstmp.getMetaData();
+
+ String stmp;
+ // Vector tuples=new Vector();
+ byte tuple[][];
+
+ // the foreign keys are only on even positions in the Vector.
+ for (i = 0;i < v.size();i += 2)
+ {
+ stmp = (String)v.elementAt(i);
+
+ for (int j = 1;j <= origCols.getColumnCount();j++)
+ {
+ if (stmp.compareTo(origCols.getColumnName(j)) == 0)
+ {
+ tuple = new byte[14][0];
+
+ for (int k = 0;k < 14;k++)
+ tuple[k] = null;
+
+ //PKTABLE_NAME
+ tuple[2] = primTable.getBytes();
+ //PKTABLE_COLUMN
+ stmp = (String)v.elementAt(i + 1);
+ tuple[3] = stmp.getBytes();
+ //FKTABLE_NAME
+ tuple[6] = origTable.getBytes();
+ //FKCOLUMN_NAME
+ tuple[7] = origCols.getColumnName(j).getBytes();
+ //KEY_SEQ
+ tuple[8] = Integer.toString(j).getBytes();
+
+ tuples.addElement(tuple);
+
+ //System.out.println(origCols.getColumnName(j)+
+ //": "+j+" -> "+primTable+": "+
+ //(String)v.elementAt(i+1));
+ break;
+ }
+ }
+ }
+
+ //return tuples;
+ }
+
+ /**
+ * Get a description of the primary key columns that are
+ * referenced by a table's foreign key columns (the primary keys
+ * imported by a table). They are ordered by PKTABLE_CAT,
+ * PKTABLE_SCHEM, PKTABLE_NAME, and KEY_SEQ.
+ *
+ * <P>Each primary key column description has the following columns:
+ * <OL>
+ * <LI><B>PKTABLE_CAT</B> String => primary key table catalog
+ * being imported (may be null)
+ * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema
+ * being imported (may be null)
+ * <LI><B>PKTABLE_NAME</B> String => primary key table name
+ * being imported
+ * <LI><B>PKCOLUMN_NAME</B> String => primary key column name
+ * being imported
+ * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
+ * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
+ * <LI><B>FKTABLE_NAME</B> String => foreign key table name
+ * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
+ * <LI><B>KEY_SEQ</B> short => sequence number within foreign key
+ * <LI><B>UPDATE_RULE</B> short => What happens to
+ * foreign key when primary is updated:
+ * <UL>
+ * <LI> importedKeyCascade - change imported key to agree
+ * with primary key update
+ * <LI> importedKeyRestrict - do not allow update of primary
+ * key if it has been imported
+ * <LI> importedKeySetNull - change imported key to NULL if
+ * its primary key has been updated
+ * </UL>
+ * <LI><B>DELETE_RULE</B> short => What happens to
+ * the foreign key when primary is deleted.
+ * <UL>
+ * <LI> importedKeyCascade - delete rows that import a deleted key
+ * <LI> importedKeyRestrict - do not allow delete of primary
+ * key if it has been imported
+ * <LI> importedKeySetNull - change imported key to NULL if
+ * its primary key has been deleted
+ * </UL>
+ * <LI><B>FK_NAME</B> String => foreign key name (may be null)
+ * <LI><B>PK_NAME</B> String => primary key name (may be null)
+ * </OL>
+ *
+ * @param catalog a catalog name; "" retrieves those without a catalog
+ * @param schema a schema name pattern; "" retrieves those
+ * without a schema
+ * @param table a table name
+ * @return ResultSet each row is a primary key column description
+ * @see #getExportedKeys
+ */
+ public java.sql.ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException
+ {
+ // Added by Ola Sundell <ola@miranda.org>
+ // FIXME: error checking galore!
+ java.sql.ResultSet rsret;
+ Field f[] = new Field[14];
+ byte tuple[][];
+
+ f[0] = new Field(connection, "PKTABLE_CAT", iVarcharOid, 32);
+ f[1] = new Field(connection, "PKTABLE_SCHEM", iVarcharOid, 32);
+ f[2] = new Field(connection, "PKTABLE_NAME", iVarcharOid, 32);
+ f[3] = new Field(connection, "PKCOLUMN_NAME", iVarcharOid, 32);
+ f[4] = new Field(connection, "FKTABLE_CAT", iVarcharOid, 32);
+ f[5] = new Field(connection, "FKTABLE_SCHEM", iVarcharOid, 32);
+ f[6] = new Field(connection, "FKTABLE_NAME", iVarcharOid, 32);
+ f[7] = new Field(connection, "FKCOLUMN_NAME", iVarcharOid, 32);
+ f[8] = new Field(connection, "KEY_SEQ", iInt2Oid, 2);
+ f[9] = new Field(connection, "UPDATE_RULE", iInt2Oid, 2);
+ f[10] = new Field(connection, "DELETE_RULE", iInt2Oid, 2);
+ f[11] = new Field(connection, "FK_NAME", iVarcharOid, 32);
+ f[12] = new Field(connection, "PK_NAME", iVarcharOid, 32);
+ f[13] = new Field(connection, "DEFERRABILITY", iInt2Oid, 2);
+
+ java.sql.ResultSet rs = connection.ExecSQL("select t.tgargs " +
+ "from pg_class as c, pg_trigger as t " +
+ "where c.relname like '" + table + "' and c.relfilenode=t.tgrelid");
+ Vector tuples = new Vector();
+
+ while (rs.next())
+ {
+ importLoop(tuples, rs);
+ }
+
+ rsret = new ResultSet(connection, f, tuples, "OK", 1);
+
+ return rsret;
+ }
+
+ /**
+ * Get a description of a foreign key columns that reference a
+ * table's primary key columns (the foreign keys exported by a
+ * table). They are ordered by FKTABLE_CAT, FKTABLE_SCHEM,
+ * FKTABLE_NAME, and KEY_SEQ.
+ *
+ * This method is currently unimplemented.
+ *
+ * <P>Each foreign key column description has the following columns:
+ * <OL>
+ * <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
+ * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
+ * <LI><B>PKTABLE_NAME</B> String => primary key table name
+ * <LI><B>PKCOLUMN_NAME</B> String => primary key column name
+ * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
+ * being exported (may be null)
+ * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
+ * being exported (may be null)
+ * <LI><B>FKTABLE_NAME</B> String => foreign key table name
+ * being exported
+ * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
+ * being exported
+ * <LI><B>KEY_SEQ</B> short => sequence number within foreign key
+ * <LI><B>UPDATE_RULE</B> short => What happens to
+ * foreign key when primary is updated:
+ * <UL>
+ * <LI> importedKeyCascade - change imported key to agree
+ * with primary key update
+ * <LI> importedKeyRestrict - do not allow update of primary
+ * key if it has been imported
+ * <LI> importedKeySetNull - change imported key to NULL if
+ * its primary key has been updated
+ * </UL>
+ * <LI><B>DELETE_RULE</B> short => What happens to
+ * the foreign key when primary is deleted.
+ * <UL>
+ * <LI> importedKeyCascade - delete rows that import a deleted key
+ * <LI> importedKeyRestrict - do not allow delete of primary
+ * key if it has been imported
+ * <LI> importedKeySetNull - change imported key to NULL if
+ * its primary key has been deleted
+ * </UL>
+ * <LI><B>FK_NAME</B> String => foreign key identifier (may be null)
+ * <LI><B>PK_NAME</B> String => primary key identifier (may be null)
+ * </OL>
+ *
+ * @param catalog a catalog name; "" retrieves those without a catalog
+ * @param schema a schema name pattern; "" retrieves those
+ * without a schema
+ * @param table a table name
+ * @return ResultSet each row is a foreign key column description
+ * @see #getImportedKeys
+ */
+ public java.sql.ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented();
+ }
+
+ /**
+ * Get a description of the foreign key columns in the foreign key
+ * table that reference the primary key columns of the primary key
+ * table (describe how one table imports another's key.) This
+ * should normally return a single foreign key/primary key pair
+ * (most tables only import a foreign key from a table once.) They
+ * are ordered by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, and
+ * KEY_SEQ.
+ *
+ * This method is currently unimplemented.
+ *
+ * <P>Each foreign key column description has the following columns:
+ * <OL>
+ * <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
+ * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
+ * <LI><B>PKTABLE_NAME</B> String => primary key table name
+ * <LI><B>PKCOLUMN_NAME</B> String => primary key column name
+ * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
+ * being exported (may be null)
+ * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
+ * being exported (may be null)
+ * <LI><B>FKTABLE_NAME</B> String => foreign key table name
+ * being exported
+ * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
+ * being exported
+ * <LI><B>KEY_SEQ</B> short => sequence number within foreign key
+ * <LI><B>UPDATE_RULE</B> short => What happens to
+ * foreign key when primary is updated:
+ * <UL>
+ * <LI> importedKeyCascade - change imported key to agree
+ * with primary key update
+ * <LI> importedKeyRestrict - do not allow update of primary
+ * key if it has been imported
+ * <LI> importedKeySetNull - change imported key to NULL if
+ * its primary key has been updated
+ * </UL>
+ * <LI><B>DELETE_RULE</B> short => What happens to
+ * the foreign key when primary is deleted.
+ * <UL>
+ * <LI> importedKeyCascade - delete rows that import a deleted key
+ * <LI> importedKeyRestrict - do not allow delete of primary
+ * key if it has been imported
+ * <LI> importedKeySetNull - change imported key to NULL if
+ * its primary key has been deleted
+ * </UL>
+ * <LI><B>FK_NAME</B> String => foreign key identifier (may be null)
+ * <LI><B>PK_NAME</B> String => primary key identifier (may be null)
+ * </OL>
+ *
+ * @param catalog a catalog name; "" retrieves those without a catalog
+ * @param schema a schema name pattern; "" retrieves those
+ * without a schema
+ * @param table a table name
+ * @return ResultSet each row is a foreign key column description
+ * @see #getImportedKeys
+ */
+ public java.sql.ResultSet getCrossReference(String primaryCatalog, String primarySchema, String primaryTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented();
+ }
+
+ /**
+ * Get a description of all the standard SQL types supported by
+ * this database. They are ordered by DATA_TYPE and then by how
+ * closely the data type maps to the corresponding JDBC SQL type.
+ *
+ * <P>Each type description has the following columns:
+ * <OL>
+ * <LI><B>TYPE_NAME</B> String => Type name
+ * <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
+ * <LI><B>PRECISION</B> int => maximum precision
+ * <LI><B>LITERAL_PREFIX</B> String => prefix used to quote a literal
+ * (may be null)
+ * <LI><B>LITERAL_SUFFIX</B> String => suffix used to quote a literal
+ (may be null)
+ * <LI><B>CREATE_PARAMS</B> String => parameters used in creating
+ * the type (may be null)
+ * <LI><B>NULLABLE</B> short => can you use NULL for this type?
+ * <UL>
+ * <LI> typeNoNulls - does not allow NULL values
+ * <LI> typeNullable - allows NULL values
+ * <LI> typeNullableUnknown - nullability unknown
+ * </UL>
+ * <LI><B>CASE_SENSITIVE</B> boolean=> is it case sensitive?
+ * <LI><B>SEARCHABLE</B> short => can you use "WHERE" based on this type:
+ * <UL>
+ * <LI> typePredNone - No support
+ * <LI> typePredChar - Only supported with WHERE .. LIKE
+ * <LI> typePredBasic - Supported except for WHERE .. LIKE
+ * <LI> typeSearchable - Supported for all WHERE ..
+ * </UL>
+ * <LI><B>UNSIGNED_ATTRIBUTE</B> boolean => is it unsigned?
+ * <LI><B>FIXED_PREC_SCALE</B> boolean => can it be a money value?
+ * <LI><B>AUTO_INCREMENT</B> boolean => can it be used for an
+ * auto-increment value?
+ * <LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name
+ * (may be null)
+ * <LI><B>MINIMUM_SCALE</B> short => minimum scale supported
+ * <LI><B>MAXIMUM_SCALE</B> short => maximum scale supported
+ * <LI><B>SQL_DATA_TYPE</B> int => unused
+ * <LI><B>SQL_DATETIME_SUB</B> int => unused
+ * <LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10
+ * </OL>
+ *
+ * @return ResultSet each row is a SQL type description
+ */
+ public java.sql.ResultSet getTypeInfo() throws SQLException
+ {
+ java.sql.ResultSet rs = connection.ExecSQL("select typname from pg_type");
+ if (rs != null)
+ {
+ Field f[] = new Field[18];
+ ResultSet r; // ResultSet for the SQL query that we need to do
+ Vector v = new Vector(); // The new ResultSet tuple stuff
+
+ f[0] = new Field(connection, "TYPE_NAME", iVarcharOid, 32);
+ f[1] = new Field(connection, "DATA_TYPE", iInt2Oid, 2);
+ f[2] = new Field(connection, "PRECISION", iInt4Oid, 4);
+ f[3] = new Field(connection, "LITERAL_PREFIX", iVarcharOid, 32);
+ f[4] = new Field(connection, "LITERAL_SUFFIX", iVarcharOid, 32);
+ f[5] = new Field(connection, "CREATE_PARAMS", iVarcharOid, 32);
+ f[6] = new Field(connection, "NULLABLE", iInt2Oid, 2);
+ f[7] = new Field(connection, "CASE_SENSITIVE", iBoolOid, 1);
+ f[8] = new Field(connection, "SEARCHABLE", iInt2Oid, 2);
+ f[9] = new Field(connection, "UNSIGNED_ATTRIBUTE", iBoolOid, 1);
+ f[10] = new Field(connection, "FIXED_PREC_SCALE", iBoolOid, 1);
+ f[11] = new Field(connection, "AUTO_INCREMENT", iBoolOid, 1);
+ f[12] = new Field(connection, "LOCAL_TYPE_NAME", iVarcharOid, 32);
+ f[13] = new Field(connection, "MINIMUM_SCALE", iInt2Oid, 2);
+ f[14] = new Field(connection, "MAXIMUM_SCALE", iInt2Oid, 2);
+ f[15] = new Field(connection, "SQL_DATA_TYPE", iInt4Oid, 4);
+ f[16] = new Field(connection, "SQL_DATETIME_SUB", iInt4Oid, 4);
+ f[17] = new Field(connection, "NUM_PREC_RADIX", iInt4Oid, 4);
+
+ // cache some results, this will keep memory useage down, and speed
+ // things up a little.
+ byte b9[] = "9".getBytes();
+ byte b10[] = "10".getBytes();
+ byte bf[] = "f".getBytes();
+ byte bnn[] = Integer.toString(typeNoNulls).getBytes();
+ byte bts[] = Integer.toString(typeSearchable).getBytes();
+
+ while (rs.next())
+ {
+ byte[][] tuple = new byte[18][];
+ String typname = rs.getString(1);
+ tuple[0] = typname.getBytes();
+ tuple[1] = Integer.toString(connection.getSQLType(typname)).getBytes();
+ tuple[2] = b9; // for now
+ tuple[6] = bnn; // for now
+ tuple[7] = bf; // false for now - not case sensitive
+ tuple[8] = bts;
+ tuple[9] = bf; // false for now - it's signed
+ tuple[10] = bf; // false for now - must handle money
+ tuple[11] = bf; // false for now - handle autoincrement
+ // 12 - LOCAL_TYPE_NAME is null
+ // 13 & 14 ?
+ // 15 & 16 are unused so we return null
+ tuple[17] = b10; // everything is base 10
+ v.addElement(tuple);
+ }
+ rs.close();
+ return new ResultSet(connection, f, v, "OK", 1);
+ }
+
+ throw new PSQLException("postgresql.metadata.unavailable");
+ }
+
+ /**
+ * Get a description of a table's indices and statistics. They are
+ * ordered by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION.
+ *
+ * <P>Each index column description has the following columns:
+ * <OL>
+ * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
+ * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
+ * <LI><B>TABLE_NAME</B> String => table name
+ * <LI><B>NON_UNIQUE</B> boolean => Can index values be non-unique?
+ * false when TYPE is tableIndexStatistic
+ * <LI><B>INDEX_QUALIFIER</B> String => index catalog (may be null);
+ * null when TYPE is tableIndexStatistic
+ * <LI><B>INDEX_NAME</B> String => index name; null when TYPE is
+ * tableIndexStatistic
+ * <LI><B>TYPE</B> short => index type:
+ * <UL>
+ * <LI> tableIndexStatistic - this identifies table statistics that are
+ * returned in conjuction with a table's index descriptions
+ * <LI> tableIndexClustered - this is a clustered index
+ * <LI> tableIndexHashed - this is a hashed index
+ * <LI> tableIndexOther - this is some other style of index
+ * </UL>
+ * <LI><B>ORDINAL_POSITION</B> short => column sequence number
+ * within index; zero when TYPE is tableIndexStatistic
+ * <LI><B>COLUMN_NAME</B> String => column name; null when TYPE is
+ * tableIndexStatistic
+ * <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending
+ * "D" => descending, may be null if sort sequence is not supported;
+ * null when TYPE is tableIndexStatistic
+ * <LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatisic then
+ * this is the number of rows in the table; otherwise it is the
+ * number of unique values in the index.
+ * <LI><B>PAGES</B> int => When TYPE is tableIndexStatisic then
+ * this is the number of pages used for the table, otherwise it
+ * is the number of pages used for the current index.
+ * <LI><B>FILTER_CONDITION</B> String => Filter condition, if any.
+ * (may be null)
+ * </OL>
+ *
+ * @param catalog a catalog name; "" retrieves those without a catalog
+ * @param schema a schema name pattern; "" retrieves those without a schema
+ * @param table a table name
+ * @param unique when true, return only indices for unique values;
+ * when false, return indices regardless of whether unique or not
+ * @param approximate when true, result is allowed to reflect approximate
+ * or out of data values; when false, results are requested to be
+ * accurate
+ * @return ResultSet each row is an index column description
+ */
+ // Implementation note: This is required for Borland's JBuilder to work
+ public java.sql.ResultSet getIndexInfo(String catalog, String schema, String tableName, boolean unique, boolean approximate) throws SQLException
+ {
+ Field f[] = new Field[13];
+ java.sql.ResultSet r; // ResultSet for the SQL query that we need to do
+ Vector v = new Vector(); // The new ResultSet tuple stuff
+
+ f[0] = new Field(connection, "TABLE_CAT", iVarcharOid, 32);
+ f[1] = new Field(connection, "TABLE_SCHEM", iVarcharOid, 32);
+ f[2] = new Field(connection, "TABLE_NAME", iVarcharOid, 32);
+ f[3] = new Field(connection, "NON_UNIQUE", iBoolOid, 1);
+ f[4] = new Field(connection, "INDEX_QUALIFIER", iVarcharOid, 32);
+ f[5] = new Field(connection, "INDEX_NAME", iVarcharOid, 32);
+ f[6] = new Field(connection, "TYPE", iInt2Oid, 2);
+ f[7] = new Field(connection, "ORDINAL_POSITION", iInt2Oid, 2);
+ f[8] = new Field(connection, "COLUMN_NAME", iVarcharOid, 32);
+ f[9] = new Field(connection, "ASC_OR_DESC", iVarcharOid, 32);
+ f[10] = new Field(connection, "CARDINALITY", iInt4Oid, 4);
+ f[11] = new Field(connection, "PAGES", iInt4Oid, 4);
+ f[12] = new Field(connection, "FILTER_CONDITION", iVarcharOid, 32);
+
+ r = connection.ExecSQL("select " +
+ "c.relname, " +
+ "x.indisunique, " +
+ "i.relname, " +
+ "x.indisclustered, " +
+ "a.amname, " +
+ "x.indkey, " +
+ "c.reltuples, " +
+ "c.relpages, " +
+ "x.indexrelid " +
+ "FROM pg_index x, pg_class c, pg_class i, pg_am a " +
+ "WHERE ((c.relname = '" + tableName.toLowerCase() + "') " +
+ " AND (c.oid = x.indrelid) " +
+ " AND (i.oid = x.indexrelid) " +
+ " AND (i.relam = a.oid)) " +
+ "ORDER BY x.indisunique DESC, " +
+ " x.indisclustered, a.amname, i.relname");
+ while (r.next())
+ {
+ // indkey is an array of column ordinals (integers). In the JDBC
+ // interface, this has to be separated out into a separate
+ // tuple for each indexed column. Also, getArray() is not yet
+ // implemented for Postgres JDBC, so we parse by hand.
+ String columnOrdinalString = r.getString(6);
+ StringTokenizer stok = new StringTokenizer(columnOrdinalString);
+ int [] columnOrdinals = new int[stok.countTokens()];
+ int o = 0;
+ while (stok.hasMoreTokens())
+ {
+ columnOrdinals[o++] = Integer.parseInt(stok.nextToken());
+ }
+ for (int i = 0; i < columnOrdinals.length; i++)
+ {
+ byte [] [] tuple = new byte [13] [];
+ tuple[0] = "".getBytes();
+ tuple[1] = "".getBytes();
+ tuple[2] = r.getBytes(1);
+ tuple[3] = r.getBoolean(2) ? "f".getBytes() : "t".getBytes();
+ tuple[4] = null;
+ tuple[5] = r.getBytes(3);
+ tuple[6] = r.getBoolean(4) ?
+ Integer.toString(tableIndexClustered).getBytes() :
+ r.getString(5).equals("hash") ?
+ Integer.toString(tableIndexHashed).getBytes() :
+ Integer.toString(tableIndexOther).getBytes();
+ tuple[7] = Integer.toString(i + 1).getBytes();
+ java.sql.ResultSet columnNameRS = connection.ExecSQL("select a.attname FROM pg_attribute a WHERE (a.attnum = " + columnOrdinals[i] + ") AND (a.attrelid = " + r.getInt(9) + ")");
+ columnNameRS.next();
+ tuple[8] = columnNameRS.getBytes(1);
+ tuple[9] = null; // sort sequence ???
+ tuple[10] = r.getBytes(7); // inexact
+ tuple[11] = r.getBytes(8);
+ tuple[12] = null;
+ v.addElement(tuple);
+ }
+ }
+
+ return new ResultSet(connection, f, v, "OK", 1);
}
- r.close();
-
- return new ResultSet(connection, f, v, "OK", 1);
- }
-
- /**
- * Get a description of the access rights for a table's columns.
- *
- * <P>Only privileges matching the column name criteria are
- * returned. They are ordered by COLUMN_NAME and PRIVILEGE.
- *
- * <P>Each privilige description has the following columns:
- * <OL>
- * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
- * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
- * <LI><B>TABLE_NAME</B> String => table name
- * <LI><B>COLUMN_NAME</B> String => column name
- * <LI><B>GRANTOR</B> => grantor of access (may be null)
- * <LI><B>GRANTEE</B> String => grantee of access
- * <LI><B>PRIVILEGE</B> String => name of access (SELECT,
- * INSERT, UPDATE, REFRENCES, ...)
- * <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
- * to grant to others; "NO" if not; null if unknown
- * </OL>
- *
- * @param catalog a catalog name; "" retrieves those without a catalog
- * @param schema a schema name; "" retrieves those without a schema
- * @param table a table name
- * @param columnNamePattern a column name pattern
- * @return ResultSet each row is a column privilege description
- * @see #getSearchStringEscape
- */
- public java.sql.ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException
- {
- Field f[] = new Field[8];
- Vector v = new Vector();
-
- if(table==null)
- table="%";
-
- if(columnNamePattern==null)
- columnNamePattern="%";
- else
- columnNamePattern=columnNamePattern.toLowerCase();
-
- f[0] = new Field(connection,"TABLE_CAT",iVarcharOid,32);
- f[1] = new Field(connection,"TABLE_SCHEM",iVarcharOid,32);
- f[2] = new Field(connection,"TABLE_NAME",iVarcharOid,32);
- f[3] = new Field(connection,"COLUMN_NAME",iVarcharOid,32);
- f[4] = new Field(connection,"GRANTOR",iVarcharOid,32);
- f[5] = new Field(connection,"GRANTEE",iVarcharOid,32);
- f[6] = new Field(connection,"PRIVILEGE",iVarcharOid,32);
- f[7] = new Field(connection,"IS_GRANTABLE",iVarcharOid,32);
-
- // This is taken direct from the psql source
- java.sql.ResultSet r = connection.ExecSQL("SELECT relname, relacl FROM pg_class, pg_user WHERE ( relkind = 'r' OR relkind = 'i') and relname !~ '^pg_' and relname !~ '^xin[vx][0-9]+' and usesysid = relowner and relname like '"+table.toLowerCase()+"' ORDER BY relname");
- while(r.next()) {
- byte[][] tuple = new byte[8][0];
- tuple[0] = tuple[1]= "".getBytes();
- DriverManager.println("relname=\""+r.getString(1)+"\" relacl=\""+r.getString(2)+"\"");
-
- // For now, don't add to the result as relacl needs to be processed.
- //v.addElement(tuple);
- }
-
- return new ResultSet(connection,f,v,"OK",1);
- }
-
- /**
- * Get a description of the access rights for each table available
- * in a catalog.
- *
- * This method is currently unimplemented.
- *
- * <P>Only privileges matching the schema and table name
- * criteria are returned. They are ordered by TABLE_SCHEM,
- * TABLE_NAME, and PRIVILEGE.
- *
- * <P>Each privilige description has the following columns:
- * <OL>
- * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
- * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
- * <LI><B>TABLE_NAME</B> String => table name
- * <LI><B>COLUMN_NAME</B> String => column name
- * <LI><B>GRANTOR</B> => grantor of access (may be null)
- * <LI><B>GRANTEE</B> String => grantee of access
- * <LI><B>PRIVILEGE</B> String => name of access (SELECT,
- * INSERT, UPDATE, REFRENCES, ...)
- * <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
- * to grant to others; "NO" if not; null if unknown
- * </OL>
- *
- * @param catalog a catalog name; "" retrieves those without a catalog
- * @param schemaPattern a schema name pattern; "" retrieves those
- * without a schema
- * @param tableNamePattern a table name pattern
- * @return ResultSet each row is a table privilege description
- * @see #getSearchStringEscape
- */
- public java.sql.ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException
- {
- throw org.postgresql.Driver.notImplemented();
- }
-
- /**
- * Get a description of a table's optimal set of columns that
- * uniquely identifies a row. They are ordered by SCOPE.
- *
- * <P>Each column description has the following columns:
- * <OL>
- * <LI><B>SCOPE</B> short => actual scope of result
- * <UL>
- * <LI> bestRowTemporary - very temporary, while using row
- * <LI> bestRowTransaction - valid for remainder of current transaction
- * <LI> bestRowSession - valid for remainder of current session
- * </UL>
- * <LI><B>COLUMN_NAME</B> String => column name
- * <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
- * <LI><B>TYPE_NAME</B> String => Data source dependent type name
- * <LI><B>COLUMN_SIZE</B> int => precision
- * <LI><B>BUFFER_LENGTH</B> int => not used
- * <LI><B>DECIMAL_DIGITS</B> short => scale
- * <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
- * like an Oracle ROWID
- * <UL>
- * <LI> bestRowUnknown - may or may not be pseudo column
- * <LI> bestRowNotPseudo - is NOT a pseudo column
- * <LI> bestRowPseudo - is a pseudo column
- * </UL>
- * </OL>
- *
- * @param catalog a catalog name; "" retrieves those without a catalog
- * @param schema a schema name; "" retrieves those without a schema
- * @param table a table name
- * @param scope the scope of interest; use same values as SCOPE
- * @param nullable include columns that are nullable?
- * @return ResultSet each row is a column description
- */
- // Implementation note: This is required for Borland's JBuilder to work
- public java.sql.ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException
- {
- // for now, this returns an empty result set.
- Field f[] = new Field[8];
- ResultSet r; // ResultSet for the SQL query that we need to do
- Vector v = new Vector(); // The new ResultSet tuple stuff
-
- f[0] = new Field(connection, "SCOPE", iInt2Oid, 2);
- f[1] = new Field(connection, "COLUMN_NAME", iVarcharOid, 32);
- f[2] = new Field(connection, "DATA_TYPE", iInt2Oid, 2);
- f[3] = new Field(connection, "TYPE_NAME", iVarcharOid, 32);
- f[4] = new Field(connection, "COLUMN_SIZE", iInt4Oid, 4);
- f[5] = new Field(connection, "BUFFER_LENGTH", iInt4Oid, 4);
- f[6] = new Field(connection, "DECIMAL_DIGITS", iInt2Oid, 2);
- f[7] = new Field(connection, "PSEUDO_COLUMN", iInt2Oid, 2);
-
- return new ResultSet(connection, f, v, "OK", 1);
- }
-
- /**
- * Get a description of a table's columns that are automatically
- * updated when any value in a row is updated. They are
- * unordered.
- *
- * This method is currently unimplemented.
- *
- * <P>Each column description has the following columns:
- * <OL>
- * <LI><B>SCOPE</B> short => is not used
- * <LI><B>COLUMN_NAME</B> String => column name
- * <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
- * <LI><B>TYPE_NAME</B> String => Data source dependent type name
- * <LI><B>COLUMN_SIZE</B> int => precision
- * <LI><B>BUFFER_LENGTH</B> int => length of column value in bytes
- * <LI><B>DECIMAL_DIGITS</B> short => scale
- * <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
- * like an Oracle ROWID
- * <UL>
- * <LI> versionColumnUnknown - may or may not be pseudo column
- * <LI> versionColumnNotPseudo - is NOT a pseudo column
- * <LI> versionColumnPseudo - is a pseudo column
- * </UL>
- * </OL>
- *
- * @param catalog a catalog name; "" retrieves those without a catalog
- * @param schema a schema name; "" retrieves those without a schema
- * @param table a table name
- * @return ResultSet each row is a column description
- */
- public java.sql.ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException
- {
- throw org.postgresql.Driver.notImplemented();
- }
-
- /**
- * Get a description of a table's primary key columns. They
- * are ordered by COLUMN_NAME.
- *
- * <P>Each column description has the following columns:
- * <OL>
- * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
- * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
- * <LI><B>TABLE_NAME</B> String => table name
- * <LI><B>COLUMN_NAME</B> String => column name
- * <LI><B>KEY_SEQ</B> short => sequence number within primary key
- * <LI><B>PK_NAME</B> String => primary key name (may be null)
- * </OL>
- *
- * @param catalog a catalog name; "" retrieves those without a catalog
- * @param schema a schema name pattern; "" retrieves those
- * without a schema
- * @param table a table name
- * @return ResultSet each row is a primary key column description
- */
- public java.sql.ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException
- {
- return connection.createStatement().executeQuery("SELECT " +
- "'' as TABLE_CAT," +
- "'' AS TABLE_SCHEM," +
- "bc.relname AS TABLE_NAME," +
- "a.attname AS COLUMN_NAME," +
- "a.attnum as KEY_SEQ,"+
- "ic.relname as PK_NAME " +
- " FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a" +
- " WHERE bc.relkind = 'r' " + // -- not indices
- " and upper(bc.relname) = upper('"+table+"')" +
- " and i.indrelid = bc.oid" +
- " and i.indexrelid = ic.oid" +
- " and ic.oid = a.attrelid" +
- " and i.indisprimary='t' " +
- " ORDER BY table_name, pk_name, key_seq"
- );
- }
-
- private void importLoop(Vector tuples, java.sql.ResultSet keyRelation) throws SQLException {
- String s,s2;
- String origTable=null, primTable=new String(""), schema;
- int i;
- Vector v=new Vector();
-
- s=keyRelation.getString(1);
- s2=s;
- //System.out.println(s);
-
- for (i=0;;i++) {
- s=s.substring(s.indexOf("\\000")+4);
- if (s.compareTo("")==0) {
- //System.out.println();
- break;
- }
- s2=s.substring(0,s.indexOf("\\000"));
- switch (i) {
- case 0:
- origTable=s2;
- break;
- case 1:
- primTable=s2;
- break;
- case 2:
- schema=s2;
- break;
- default:
- v.addElement(s2);
- }
- }
-
- java.sql.ResultSet rstmp=connection.ExecSQL("select * from "+origTable+" where 1=0");
- java.sql.ResultSetMetaData origCols=rstmp.getMetaData();
-
- String stmp;
- // Vector tuples=new Vector();
- byte tuple[][];
-
- // the foreign keys are only on even positions in the Vector.
- for (i=0;i<v.size();i+=2) {
- stmp=(String)v.elementAt(i);
-
- for (int j=1;j<=origCols.getColumnCount();j++) {
- if (stmp.compareTo(origCols.getColumnName(j))==0) {
- tuple=new byte[14][0];
-
- for (int k=0;k<14;k++)
- tuple[k]=null;
-
- //PKTABLE_NAME
- tuple[2]=primTable.getBytes();
- //PKTABLE_COLUMN
- stmp=(String)v.elementAt(i+1);
- tuple[3]=stmp.getBytes();
- //FKTABLE_NAME
- tuple[6]=origTable.getBytes();
- //FKCOLUMN_NAME
- tuple[7]=origCols.getColumnName(j).getBytes();
- //KEY_SEQ
- tuple[8]=Integer.toString(j).getBytes();
-
- tuples.addElement(tuple);
-
- //System.out.println(origCols.getColumnName(j)+
- //": "+j+" -> "+primTable+": "+
- //(String)v.elementAt(i+1));
- break;
- }
- }
- }
-
- //return tuples;
- }
-
- /**
- * Get a description of the primary key columns that are
- * referenced by a table's foreign key columns (the primary keys
- * imported by a table). They are ordered by PKTABLE_CAT,
- * PKTABLE_SCHEM, PKTABLE_NAME, and KEY_SEQ.
- *
- * <P>Each primary key column description has the following columns:
- * <OL>
- * <LI><B>PKTABLE_CAT</B> String => primary key table catalog
- * being imported (may be null)
- * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema
- * being imported (may be null)
- * <LI><B>PKTABLE_NAME</B> String => primary key table name
- * being imported
- * <LI><B>PKCOLUMN_NAME</B> String => primary key column name
- * being imported
- * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
- * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
- * <LI><B>FKTABLE_NAME</B> String => foreign key table name
- * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
- * <LI><B>KEY_SEQ</B> short => sequence number within foreign key
- * <LI><B>UPDATE_RULE</B> short => What happens to
- * foreign key when primary is updated:
- * <UL>
- * <LI> importedKeyCascade - change imported key to agree
- * with primary key update
- * <LI> importedKeyRestrict - do not allow update of primary
- * key if it has been imported
- * <LI> importedKeySetNull - change imported key to NULL if
- * its primary key has been updated
- * </UL>
- * <LI><B>DELETE_RULE</B> short => What happens to
- * the foreign key when primary is deleted.
- * <UL>
- * <LI> importedKeyCascade - delete rows that import a deleted key
- * <LI> importedKeyRestrict - do not allow delete of primary
- * key if it has been imported
- * <LI> importedKeySetNull - change imported key to NULL if
- * its primary key has been deleted
- * </UL>
- * <LI><B>FK_NAME</B> String => foreign key name (may be null)
- * <LI><B>PK_NAME</B> String => primary key name (may be null)
- * </OL>
- *
- * @param catalog a catalog name; "" retrieves those without a catalog
- * @param schema a schema name pattern; "" retrieves those
- * without a schema
- * @param table a table name
- * @return ResultSet each row is a primary key column description
- * @see #getExportedKeys
- */
- public java.sql.ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException
- {
- // Added by Ola Sundell <ola@miranda.org>
- // FIXME: error checking galore!
- java.sql.ResultSet rsret;
- Field f[]=new Field[14];
- byte tuple[][];
-
- f[0]=new Field(connection, "PKTABLE_CAT", iVarcharOid, 32);
- f[1]=new Field(connection, "PKTABLE_SCHEM", iVarcharOid, 32);
- f[2]=new Field(connection, "PKTABLE_NAME", iVarcharOid, 32);
- f[3]=new Field(connection, "PKCOLUMN_NAME", iVarcharOid, 32);
- f[4]=new Field(connection, "FKTABLE_CAT", iVarcharOid, 32);
- f[5]=new Field(connection, "FKTABLE_SCHEM", iVarcharOid, 32);
- f[6]=new Field(connection, "FKTABLE_NAME", iVarcharOid, 32);
- f[7]=new Field(connection, "FKCOLUMN_NAME", iVarcharOid, 32);
- f[8]=new Field(connection, "KEY_SEQ", iInt2Oid, 2);
- f[9]=new Field(connection, "UPDATE_RULE", iInt2Oid, 2);
- f[10]=new Field(connection, "DELETE_RULE", iInt2Oid, 2);
- f[11]=new Field(connection, "FK_NAME", iVarcharOid, 32);
- f[12]=new Field(connection, "PK_NAME", iVarcharOid, 32);
- f[13]=new Field(connection, "DEFERRABILITY", iInt2Oid, 2);
-
- java.sql.ResultSet rs=connection.ExecSQL("select t.tgargs "+
- "from pg_class as c, pg_trigger as t "+
- "where c.relname like '"+table+"' and c.relfilenode=t.tgrelid");
- Vector tuples=new Vector();
-
- while (rs.next()) {
- importLoop(tuples,rs);
- }
-
- rsret=new ResultSet(connection, f, tuples, "OK", 1);
-
- return rsret;
- }
-
- /**
- * Get a description of a foreign key columns that reference a
- * table's primary key columns (the foreign keys exported by a
- * table). They are ordered by FKTABLE_CAT, FKTABLE_SCHEM,
- * FKTABLE_NAME, and KEY_SEQ.
- *
- * This method is currently unimplemented.
- *
- * <P>Each foreign key column description has the following columns:
- * <OL>
- * <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
- * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
- * <LI><B>PKTABLE_NAME</B> String => primary key table name
- * <LI><B>PKCOLUMN_NAME</B> String => primary key column name
- * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
- * being exported (may be null)
- * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
- * being exported (may be null)
- * <LI><B>FKTABLE_NAME</B> String => foreign key table name
- * being exported
- * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
- * being exported
- * <LI><B>KEY_SEQ</B> short => sequence number within foreign key
- * <LI><B>UPDATE_RULE</B> short => What happens to
- * foreign key when primary is updated:
- * <UL>
- * <LI> importedKeyCascade - change imported key to agree
- * with primary key update
- * <LI> importedKeyRestrict - do not allow update of primary
- * key if it has been imported
- * <LI> importedKeySetNull - change imported key to NULL if
- * its primary key has been updated
- * </UL>
- * <LI><B>DELETE_RULE</B> short => What happens to
- * the foreign key when primary is deleted.
- * <UL>
- * <LI> importedKeyCascade - delete rows that import a deleted key
- * <LI> importedKeyRestrict - do not allow delete of primary
- * key if it has been imported
- * <LI> importedKeySetNull - change imported key to NULL if
- * its primary key has been deleted
- * </UL>
- * <LI><B>FK_NAME</B> String => foreign key identifier (may be null)
- * <LI><B>PK_NAME</B> String => primary key identifier (may be null)
- * </OL>
- *
- * @param catalog a catalog name; "" retrieves those without a catalog
- * @param schema a schema name pattern; "" retrieves those
- * without a schema
- * @param table a table name
- * @return ResultSet each row is a foreign key column description
- * @see #getImportedKeys
- */
- public java.sql.ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException
- {
- throw org.postgresql.Driver.notImplemented();
- }
-
- /**
- * Get a description of the foreign key columns in the foreign key
- * table that reference the primary key columns of the primary key
- * table (describe how one table imports another's key.) This
- * should normally return a single foreign key/primary key pair
- * (most tables only import a foreign key from a table once.) They
- * are ordered by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, and
- * KEY_SEQ.
- *
- * This method is currently unimplemented.
- *
- * <P>Each foreign key column description has the following columns:
- * <OL>
- * <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
- * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
- * <LI><B>PKTABLE_NAME</B> String => primary key table name
- * <LI><B>PKCOLUMN_NAME</B> String => primary key column name
- * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
- * being exported (may be null)
- * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
- * being exported (may be null)
- * <LI><B>FKTABLE_NAME</B> String => foreign key table name
- * being exported
- * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
- * being exported
- * <LI><B>KEY_SEQ</B> short => sequence number within foreign key
- * <LI><B>UPDATE_RULE</B> short => What happens to
- * foreign key when primary is updated:
- * <UL>
- * <LI> importedKeyCascade - change imported key to agree
- * with primary key update
- * <LI> importedKeyRestrict - do not allow update of primary
- * key if it has been imported
- * <LI> importedKeySetNull - change imported key to NULL if
- * its primary key has been updated
- * </UL>
- * <LI><B>DELETE_RULE</B> short => What happens to
- * the foreign key when primary is deleted.
- * <UL>
- * <LI> importedKeyCascade - delete rows that import a deleted key
- * <LI> importedKeyRestrict - do not allow delete of primary
- * key if it has been imported
- * <LI> importedKeySetNull - change imported key to NULL if
- * its primary key has been deleted
- * </UL>
- * <LI><B>FK_NAME</B> String => foreign key identifier (may be null)
- * <LI><B>PK_NAME</B> String => primary key identifier (may be null)
- * </OL>
- *
- * @param catalog a catalog name; "" retrieves those without a catalog
- * @param schema a schema name pattern; "" retrieves those
- * without a schema
- * @param table a table name
- * @return ResultSet each row is a foreign key column description
- * @see #getImportedKeys
- */
- public java.sql.ResultSet getCrossReference(String primaryCatalog, String primarySchema, String primaryTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException
- {
- throw org.postgresql.Driver.notImplemented();
- }
-
- /**
- * Get a description of all the standard SQL types supported by
- * this database. They are ordered by DATA_TYPE and then by how
- * closely the data type maps to the corresponding JDBC SQL type.
- *
- * <P>Each type description has the following columns:
- * <OL>
- * <LI><B>TYPE_NAME</B> String => Type name
- * <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
- * <LI><B>PRECISION</B> int => maximum precision
- * <LI><B>LITERAL_PREFIX</B> String => prefix used to quote a literal
- * (may be null)
- * <LI><B>LITERAL_SUFFIX</B> String => suffix used to quote a literal
- (may be null)
- * <LI><B>CREATE_PARAMS</B> String => parameters used in creating
- * the type (may be null)
- * <LI><B>NULLABLE</B> short => can you use NULL for this type?
- * <UL>
- * <LI> typeNoNulls - does not allow NULL values
- * <LI> typeNullable - allows NULL values
- * <LI> typeNullableUnknown - nullability unknown
- * </UL>
- * <LI><B>CASE_SENSITIVE</B> boolean=> is it case sensitive?
- * <LI><B>SEARCHABLE</B> short => can you use "WHERE" based on this type:
- * <UL>
- * <LI> typePredNone - No support
- * <LI> typePredChar - Only supported with WHERE .. LIKE
- * <LI> typePredBasic - Supported except for WHERE .. LIKE
- * <LI> typeSearchable - Supported for all WHERE ..
- * </UL>
- * <LI><B>UNSIGNED_ATTRIBUTE</B> boolean => is it unsigned?
- * <LI><B>FIXED_PREC_SCALE</B> boolean => can it be a money value?
- * <LI><B>AUTO_INCREMENT</B> boolean => can it be used for an
- * auto-increment value?
- * <LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name
- * (may be null)
- * <LI><B>MINIMUM_SCALE</B> short => minimum scale supported
- * <LI><B>MAXIMUM_SCALE</B> short => maximum scale supported
- * <LI><B>SQL_DATA_TYPE</B> int => unused
- * <LI><B>SQL_DATETIME_SUB</B> int => unused
- * <LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10
- * </OL>
- *
- * @return ResultSet each row is a SQL type description
- */
- public java.sql.ResultSet getTypeInfo() throws SQLException
- {
- java.sql.ResultSet rs = connection.ExecSQL("select typname from pg_type");
- if(rs!=null) {
- Field f[] = new Field[18];
- ResultSet r; // ResultSet for the SQL query that we need to do
- Vector v = new Vector(); // The new ResultSet tuple stuff
-
- f[0] = new Field(connection, "TYPE_NAME", iVarcharOid, 32);
- f[1] = new Field(connection, "DATA_TYPE", iInt2Oid, 2);
- f[2] = new Field(connection, "PRECISION", iInt4Oid, 4);
- f[3] = new Field(connection, "LITERAL_PREFIX", iVarcharOid, 32);
- f[4] = new Field(connection, "LITERAL_SUFFIX", iVarcharOid, 32);
- f[5] = new Field(connection, "CREATE_PARAMS", iVarcharOid, 32);
- f[6] = new Field(connection, "NULLABLE", iInt2Oid, 2);
- f[7] = new Field(connection, "CASE_SENSITIVE", iBoolOid, 1);
- f[8] = new Field(connection, "SEARCHABLE", iInt2Oid, 2);
- f[9] = new Field(connection, "UNSIGNED_ATTRIBUTE", iBoolOid, 1);
- f[10] = new Field(connection, "FIXED_PREC_SCALE", iBoolOid, 1);
- f[11] = new Field(connection, "AUTO_INCREMENT", iBoolOid, 1);
- f[12] = new Field(connection, "LOCAL_TYPE_NAME", iVarcharOid, 32);
- f[13] = new Field(connection, "MINIMUM_SCALE", iInt2Oid, 2);
- f[14] = new Field(connection, "MAXIMUM_SCALE", iInt2Oid, 2);
- f[15] = new Field(connection, "SQL_DATA_TYPE", iInt4Oid, 4);
- f[16] = new Field(connection, "SQL_DATETIME_SUB", iInt4Oid, 4);
- f[17] = new Field(connection, "NUM_PREC_RADIX", iInt4Oid, 4);
-
- // cache some results, this will keep memory useage down, and speed
- // things up a little.
- byte b9[] = "9".getBytes();
- byte b10[] = "10".getBytes();
- byte bf[] = "f".getBytes();
- byte bnn[] = Integer.toString(typeNoNulls).getBytes();
- byte bts[] = Integer.toString(typeSearchable).getBytes();
-
- while(rs.next()) {
- byte[][] tuple = new byte[18][];
- String typname=rs.getString(1);
- tuple[0] = typname.getBytes();
- tuple[1] = Integer.toString(connection.getSQLType(typname)).getBytes();
- tuple[2] = b9; // for now
- tuple[6] = bnn; // for now
- tuple[7] = bf; // false for now - not case sensitive
- tuple[8] = bts;
- tuple[9] = bf; // false for now - it's signed
- tuple[10] = bf; // false for now - must handle money
- tuple[11] = bf; // false for now - handle autoincrement
- // 12 - LOCAL_TYPE_NAME is null
- // 13 & 14 ?
- // 15 & 16 are unused so we return null
- tuple[17] = b10; // everything is base 10
- v.addElement(tuple);
- }
- rs.close();
- return new ResultSet(connection, f, v, "OK", 1);
- }
-
- throw new PSQLException("postgresql.metadata.unavailable");
- }
-
- /**
- * Get a description of a table's indices and statistics. They are
- * ordered by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION.
- *
- * <P>Each index column description has the following columns:
- * <OL>
- * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
- * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
- * <LI><B>TABLE_NAME</B> String => table name
- * <LI><B>NON_UNIQUE</B> boolean => Can index values be non-unique?
- * false when TYPE is tableIndexStatistic
- * <LI><B>INDEX_QUALIFIER</B> String => index catalog (may be null);
- * null when TYPE is tableIndexStatistic
- * <LI><B>INDEX_NAME</B> String => index name; null when TYPE is
- * tableIndexStatistic
- * <LI><B>TYPE</B> short => index type:
- * <UL>
- * <LI> tableIndexStatistic - this identifies table statistics that are
- * returned in conjuction with a table's index descriptions
- * <LI> tableIndexClustered - this is a clustered index
- * <LI> tableIndexHashed - this is a hashed index
- * <LI> tableIndexOther - this is some other style of index
- * </UL>
- * <LI><B>ORDINAL_POSITION</B> short => column sequence number
- * within index; zero when TYPE is tableIndexStatistic
- * <LI><B>COLUMN_NAME</B> String => column name; null when TYPE is
- * tableIndexStatistic
- * <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending
- * "D" => descending, may be null if sort sequence is not supported;
- * null when TYPE is tableIndexStatistic
- * <LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatisic then
- * this is the number of rows in the table; otherwise it is the
- * number of unique values in the index.
- * <LI><B>PAGES</B> int => When TYPE is tableIndexStatisic then
- * this is the number of pages used for the table, otherwise it
- * is the number of pages used for the current index.
- * <LI><B>FILTER_CONDITION</B> String => Filter condition, if any.
- * (may be null)
- * </OL>
- *
- * @param catalog a catalog name; "" retrieves those without a catalog
- * @param schema a schema name pattern; "" retrieves those without a schema
- * @param table a table name
- * @param unique when true, return only indices for unique values;
- * when false, return indices regardless of whether unique or not
- * @param approximate when true, result is allowed to reflect approximate
- * or out of data values; when false, results are requested to be
- * accurate
- * @return ResultSet each row is an index column description
- */
- // Implementation note: This is required for Borland's JBuilder to work
- public java.sql.ResultSet getIndexInfo(String catalog, String schema, String tableName, boolean unique, boolean approximate) throws SQLException
- {
- Field f[] = new Field[13];
- java.sql.ResultSet r; // ResultSet for the SQL query that we need to do
- Vector v = new Vector(); // The new ResultSet tuple stuff
-
- f[0] = new Field(connection, "TABLE_CAT", iVarcharOid, 32);
- f[1] = new Field(connection, "TABLE_SCHEM", iVarcharOid, 32);
- f[2] = new Field(connection, "TABLE_NAME", iVarcharOid, 32);
- f[3] = new Field(connection, "NON_UNIQUE", iBoolOid, 1);
- f[4] = new Field(connection, "INDEX_QUALIFIER", iVarcharOid, 32);
- f[5] = new Field(connection, "INDEX_NAME", iVarcharOid, 32);
- f[6] = new Field(connection, "TYPE", iInt2Oid, 2);
- f[7] = new Field(connection, "ORDINAL_POSITION", iInt2Oid, 2);
- f[8] = new Field(connection, "COLUMN_NAME", iVarcharOid, 32);
- f[9] = new Field(connection, "ASC_OR_DESC", iVarcharOid, 32);
- f[10] = new Field(connection, "CARDINALITY", iInt4Oid, 4);
- f[11] = new Field(connection, "PAGES", iInt4Oid, 4);
- f[12] = new Field(connection, "FILTER_CONDITION", iVarcharOid, 32);
-
- r = connection.ExecSQL("select " +
- "c.relname, " +
- "x.indisunique, " +
- "i.relname, " +
- "x.indisclustered, " +
- "a.amname, " +
- "x.indkey, " +
- "c.reltuples, " +
- "c.relpages, " +
- "x.indexrelid " +
- "FROM pg_index x, pg_class c, pg_class i, pg_am a " +
- "WHERE ((c.relname = '" + tableName.toLowerCase() + "') " +
- " AND (c.oid = x.indrelid) " +
- " AND (i.oid = x.indexrelid) " +
- " AND (i.relam = a.oid)) " +
- "ORDER BY x.indisunique DESC, " +
- " x.indisclustered, a.amname, i.relname");
- while (r.next()) {
- // indkey is an array of column ordinals (integers). In the JDBC
- // interface, this has to be separated out into a separate
- // tuple for each indexed column. Also, getArray() is not yet
- // implemented for Postgres JDBC, so we parse by hand.
- String columnOrdinalString = r.getString(6);
- StringTokenizer stok = new StringTokenizer(columnOrdinalString);
- int [] columnOrdinals = new int[stok.countTokens()];
- int o = 0;
- while (stok.hasMoreTokens()) {
- columnOrdinals[o++] = Integer.parseInt(stok.nextToken());
- }
- for (int i = 0; i < columnOrdinals.length; i++) {
- byte [] [] tuple = new byte [13] [];
- tuple[0] = "".getBytes();
- tuple[1] = "".getBytes();
- tuple[2] = r.getBytes(1);
- tuple[3] = r.getBoolean(2) ? "f".getBytes() : "t".getBytes();
- tuple[4] = null;
- tuple[5] = r.getBytes(3);
- tuple[6] = r.getBoolean(4) ?
- Integer.toString(tableIndexClustered).getBytes() :
- r.getString(5).equals("hash") ?
- Integer.toString(tableIndexHashed).getBytes() :
- Integer.toString(tableIndexOther).getBytes();
- tuple[7] = Integer.toString(i + 1).getBytes();
- java.sql.ResultSet columnNameRS = connection.ExecSQL("select a.attname FROM pg_attribute a WHERE (a.attnum = " + columnOrdinals[i] + ") AND (a.attrelid = " + r.getInt(9) + ")");
- columnNameRS.next();
- tuple[8] = columnNameRS.getBytes(1);
- tuple[9] = null; // sort sequence ???
- tuple[10] = r.getBytes(7); // inexact
- tuple[11] = r.getBytes(8);
- tuple[12] = null;
- v.addElement(tuple);
- }
- }
-
- return new ResultSet(connection, f, v, "OK", 1);
- }
}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/PreparedStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/PreparedStatement.java
index 0c850e36ea0..2fd10f4698d 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/PreparedStatement.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/PreparedStatement.java
@@ -23,13 +23,13 @@ import org.postgresql.util.*;
* parameter. For instance, if the IN parameter has SQL type Integer, then
* setInt should be used.
*
- * <p>If arbitrary parameter type conversions are required, then the setObject
+ * <p>If arbitrary parameter type conversions are required, then the setObject
* method should be used with a target SQL type.
*
* @see ResultSet
* @see java.sql.PreparedStatement
*/
-public class PreparedStatement extends Statement implements java.sql.PreparedStatement
+public class PreparedStatement extends Statement implements java.sql.PreparedStatement
{
String sql;
String[] templateStrings;
@@ -82,7 +82,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
* A Prepared SQL query is executed and its ResultSet is returned
*
* @return a ResultSet that contains the data produced by the
- * * query - never null
+ * * query - never null
* @exception SQLException if a database access error occurs
*/
public java.sql.ResultSet executeQuery() throws SQLException
@@ -93,12 +93,12 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
for (i = 0 ; i < inStrings.length ; ++i)
{
if (inStrings[i] == null)
- throw new PSQLException("postgresql.prep.param",new Integer(i + 1));
+ throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
s.append (templateStrings[i]);
s.append (inStrings[i]);
}
s.append(templateStrings[inStrings.length]);
- return super.executeQuery(s.toString()); // in Statement class
+ return super.executeQuery(s.toString()); // in Statement class
}
/**
@@ -107,7 +107,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
* be executed.
*
* @return either the row count for INSERT, UPDATE or DELETE; or
- * * 0 for SQL statements that return nothing.
+ * * 0 for SQL statements that return nothing.
* @exception SQLException if a database access error occurs
*/
public int executeUpdate() throws SQLException
@@ -118,13 +118,13 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
for (i = 0 ; i < inStrings.length ; ++i)
{
if (inStrings[i] == null)
- throw new PSQLException("postgresql.prep.param",new Integer(i + 1));
+ throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
s.append (templateStrings[i]);
s.append (inStrings[i]);
}
s.append(templateStrings[inStrings.length]);
- return super.executeUpdate(s.toString()); // in Statement class
- }
+ return super.executeUpdate(s.toString()); // in Statement class
+ }
/**
* Set a parameter to SQL NULL
@@ -220,7 +220,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
}
/**
- * Set a parameter to a Java double value. The driver converts this
+ * Set a parameter to a Java double value. The driver converts this
* to a SQL DOUBLE value when it sends it to the database
*
* @param parameterIndex the first parameter is 1...
@@ -247,7 +247,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
}
/**
- * Set a parameter to a Java String value. The driver converts this
+ * Set a parameter to a Java String value. The driver converts this
* to a SQL VARCHAR or LONGVARCHAR value (depending on the arguments
* size relative to the driver's limits on VARCHARs) when it sends it
* to the database.
@@ -258,59 +258,66 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
*/
public void setString(int parameterIndex, String x) throws SQLException
{
- // if the passed string is null, then set this column to null
- if(x==null)
- setNull(parameterIndex,Types.OTHER);
- else {
- StringBuffer b = new StringBuffer();
- int i;
-
- b.append('\'');
- for (i = 0 ; i < x.length() ; ++i)
- {
- char c = x.charAt(i);
- if (c == '\\' || c == '\'')
- b.append((char)'\\');
- b.append(c);
- }
- b.append('\'');
- set(parameterIndex, b.toString());
- }
+ // if the passed string is null, then set this column to null
+ if (x == null)
+ setNull(parameterIndex, Types.OTHER);
+ else
+ {
+ StringBuffer b = new StringBuffer();
+ int i;
+
+ b.append('\'');
+ for (i = 0 ; i < x.length() ; ++i)
+ {
+ char c = x.charAt(i);
+ if (c == '\\' || c == '\'')
+ b.append((char)'\\');
+ b.append(c);
+ }
+ b.append('\'');
+ set(parameterIndex, b.toString());
+ }
}
- /**
- * Set a parameter to a Java array of bytes. The driver converts this
- * to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
- * size relative to the driver's limits on VARBINARYs) when it sends
- * it to the database.
- *
- * <p>Implementation note:
- * <br>With org.postgresql, this creates a large object, and stores the
- * objects oid in this column.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setBytes(int parameterIndex, byte x[]) throws SQLException
- {
- if (connection.haveMinimumCompatibleVersion("7.2")) {
- //Version 7.2 supports the bytea datatype for byte arrays
- if(null == x){
- setNull(parameterIndex,Types.OTHER);
- } else {
- setString(parameterIndex, PGbytea.toPGString(x));
- }
- } else {
- //Version 7.1 and earlier support done as LargeObjects
- LargeObjectManager lom = connection.getLargeObjectAPI();
- int oid = lom.create();
- LargeObject lob = lom.open(oid);
- lob.write(x);
- lob.close();
- setInt(parameterIndex,oid);
- }
- }
+ /**
+ * Set a parameter to a Java array of bytes. The driver converts this
+ * to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
+ * size relative to the driver's limits on VARBINARYs) when it sends
+ * it to the database.
+ *
+ * <p>Implementation note:
+ * <br>With org.postgresql, this creates a large object, and stores the
+ * objects oid in this column.
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ * @exception SQLException if a database access error occurs
+ */
+ public void setBytes(int parameterIndex, byte x[]) throws SQLException
+ {
+ if (connection.haveMinimumCompatibleVersion("7.2"))
+ {
+ //Version 7.2 supports the bytea datatype for byte arrays
+ if (null == x)
+ {
+ setNull(parameterIndex, Types.OTHER);
+ }
+ else
+ {
+ setString(parameterIndex, PGbytea.toPGString(x));
+ }
+ }
+ else
+ {
+ //Version 7.1 and earlier support done as LargeObjects
+ LargeObjectManager lom = connection.getLargeObjectAPI();
+ int oid = lom.create();
+ LargeObject lob = lom.open(oid);
+ lob.write(x);
+ lob.close();
+ setInt(parameterIndex, oid);
+ }
+ }
/**
* Set a parameter to a java.sql.Date value. The driver converts this
@@ -322,24 +329,27 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
*/
public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
{
- if (null == x){
- setNull(parameterIndex,Types.OTHER);
- }else{
- SimpleDateFormat df = new SimpleDateFormat("''yyyy-MM-dd''");
- set(parameterIndex, df.format(x));
- }
- // The above is how the date should be handled.
- //
- // However, in JDK's prior to 1.1.6 (confirmed with the
- // Linux jdk1.1.3 and the Win95 JRE1.1.5), SimpleDateFormat seems
- // to format a date to the previous day. So the fix is to add a day
- // before formatting.
- //
- // PS: 86400000 is one day
- //
- //set(parameterIndex, df.format(new java.util.Date(x.getTime()+86400000)));
+ if (null == x)
+ {
+ setNull(parameterIndex, Types.OTHER);
+ }
+ else
+ {
+ SimpleDateFormat df = new SimpleDateFormat("''yyyy-MM-dd''");
+ set(parameterIndex, df.format(x));
+ }
+ // The above is how the date should be handled.
+ //
+ // However, in JDK's prior to 1.1.6 (confirmed with the
+ // Linux jdk1.1.3 and the Win95 JRE1.1.5), SimpleDateFormat seems
+ // to format a date to the previous day. So the fix is to add a day
+ // before formatting.
+ //
+ // PS: 86400000 is one day
+ //
+ //set(parameterIndex, df.format(new java.util.Date(x.getTime()+86400000)));
}
-
+
/**
* Set a parameter to a java.sql.Time value. The driver converts
* this to a SQL TIME value when it sends it to the database.
@@ -350,11 +360,14 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
*/
public void setTime(int parameterIndex, Time x) throws SQLException
{
- if (null == x){
- setNull(parameterIndex,Types.OTHER);
- }else{
- set(parameterIndex, "'" + x.toString() + "'");
- }
+ if (null == x)
+ {
+ setNull(parameterIndex, Types.OTHER);
+ }
+ else
+ {
+ set(parameterIndex, "'" + x.toString() + "'");
+ }
}
/**
@@ -366,16 +379,19 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
* @exception SQLException if a database access error occurs
*/
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
- {
- if (null == x){
- setNull(parameterIndex,Types.OTHER);
- }else{
- SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- df.setTimeZone(TimeZone.getTimeZone("GMT"));
- StringBuffer strBuf = new StringBuffer("'");
- strBuf.append(df.format(x)).append('.').append(x.getNanos()/10000000).append("+00'");
- set(parameterIndex, strBuf.toString());
- }
+ {
+ if (null == x)
+ {
+ setNull(parameterIndex, Types.OTHER);
+ }
+ else
+ {
+ SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ df.setTimeZone(TimeZone.getTimeZone("GMT"));
+ StringBuffer strBuf = new StringBuffer("'");
+ strBuf.append(df.format(x)).append('.').append(x.getNanos() / 10000000).append("+00'");
+ set(parameterIndex, strBuf.toString());
+ }
}
/**
@@ -396,29 +412,37 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
*/
public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException
{
- if (connection.haveMinimumCompatibleVersion("7.2")) {
- //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
- //As the spec/javadoc for this method indicate this is to be used for
- //large String values (i.e. LONGVARCHAR) PG doesn't have a separate
- //long varchar datatype, but with toast all text datatypes are capable of
- //handling very large values. Thus the implementation ends up calling
- //setString() since there is no current way to stream the value to the server
- try {
- InputStreamReader l_inStream = new InputStreamReader(x, "ASCII");
- char[] l_chars = new char[length];
- int l_charsRead = l_inStream.read(l_chars,0,length);
- setString(parameterIndex, new String(l_chars,0,l_charsRead));
- } catch (UnsupportedEncodingException l_uee) {
- throw new PSQLException("postgresql.unusual",l_uee);
- } catch (IOException l_ioe) {
- throw new PSQLException("postgresql.unusual",l_ioe);
- }
- } else {
- //Version 7.1 supported only LargeObjects by treating everything
- //as binary data
- setBinaryStream(parameterIndex, x, length);
+ if (connection.haveMinimumCompatibleVersion("7.2"))
+ {
+ //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
+ //As the spec/javadoc for this method indicate this is to be used for
+ //large String values (i.e. LONGVARCHAR) PG doesn't have a separate
+ //long varchar datatype, but with toast all text datatypes are capable of
+ //handling very large values. Thus the implementation ends up calling
+ //setString() since there is no current way to stream the value to the server
+ try
+ {
+ InputStreamReader l_inStream = new InputStreamReader(x, "ASCII");
+ char[] l_chars = new char[length];
+ int l_charsRead = l_inStream.read(l_chars, 0, length);
+ setString(parameterIndex, new String(l_chars, 0, l_charsRead));
+ }
+ catch (UnsupportedEncodingException l_uee)
+ {
+ throw new PSQLException("postgresql.unusual", l_uee);
+ }
+ catch (IOException l_ioe)
+ {
+ throw new PSQLException("postgresql.unusual", l_ioe);
+ }
+ }
+ else
+ {
+ //Version 7.1 supported only LargeObjects by treating everything
+ //as binary data
+ setBinaryStream(parameterIndex, x, length);
+ }
}
- }
/**
* When a very large Unicode value is input to a LONGVARCHAR parameter,
@@ -437,35 +461,43 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
*/
public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException
{
- if (connection.haveMinimumCompatibleVersion("7.2")) {
- //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
- //As the spec/javadoc for this method indicate this is to be used for
- //large String values (i.e. LONGVARCHAR) PG doesn't have a separate
- //long varchar datatype, but with toast all text datatypes are capable of
- //handling very large values. Thus the implementation ends up calling
- //setString() since there is no current way to stream the value to the server
- try {
- InputStreamReader l_inStream = new InputStreamReader(x, "UTF-8");
- char[] l_chars = new char[length];
- int l_charsRead = l_inStream.read(l_chars,0,length);
- setString(parameterIndex, new String(l_chars,0,l_charsRead));
- } catch (UnsupportedEncodingException l_uee) {
- throw new PSQLException("postgresql.unusual",l_uee);
- } catch (IOException l_ioe) {
- throw new PSQLException("postgresql.unusual",l_ioe);
- }
- } else {
- //Version 7.1 supported only LargeObjects by treating everything
- //as binary data
- setBinaryStream(parameterIndex, x, length);
+ if (connection.haveMinimumCompatibleVersion("7.2"))
+ {
+ //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
+ //As the spec/javadoc for this method indicate this is to be used for
+ //large String values (i.e. LONGVARCHAR) PG doesn't have a separate
+ //long varchar datatype, but with toast all text datatypes are capable of
+ //handling very large values. Thus the implementation ends up calling
+ //setString() since there is no current way to stream the value to the server
+ try
+ {
+ InputStreamReader l_inStream = new InputStreamReader(x, "UTF-8");
+ char[] l_chars = new char[length];
+ int l_charsRead = l_inStream.read(l_chars, 0, length);
+ setString(parameterIndex, new String(l_chars, 0, l_charsRead));
+ }
+ catch (UnsupportedEncodingException l_uee)
+ {
+ throw new PSQLException("postgresql.unusual", l_uee);
+ }
+ catch (IOException l_ioe)
+ {
+ throw new PSQLException("postgresql.unusual", l_ioe);
+ }
+ }
+ else
+ {
+ //Version 7.1 supported only LargeObjects by treating everything
+ //as binary data
+ setBinaryStream(parameterIndex, x, length);
+ }
}
- }
/**
* When a very large binary value is input to a LONGVARBINARY parameter,
* it may be more practical to send it via a java.io.InputStream.
* JDBC will read the data from the stream as needed, until it reaches
- * end-of-file.
+ * end-of-file.
*
* <P><B>Note:</B> This stream object can either be a standard Java
* stream object or your own subclass that implements the standard
@@ -477,60 +509,73 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
*/
public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException
{
- if (connection.haveMinimumCompatibleVersion("7.2")) {
- //Version 7.2 supports BinaryStream for for the PG bytea type
- //As the spec/javadoc for this method indicate this is to be used for
- //large binary values (i.e. LONGVARBINARY) PG doesn't have a separate
- //long binary datatype, but with toast the bytea datatype is capable of
- //handling very large values. Thus the implementation ends up calling
- //setBytes() since there is no current way to stream the value to the server
- byte[] l_bytes = new byte[length];
- int l_bytesRead;
- try {
- l_bytesRead = x.read(l_bytes,0,length);
- } catch (IOException l_ioe) {
- throw new PSQLException("postgresql.unusual",l_ioe);
- }
- if (l_bytesRead == length) {
- setBytes(parameterIndex, l_bytes);
- } else {
- //the stream contained less data than they said
- byte[] l_bytes2 = new byte[l_bytesRead];
- System.arraycopy(l_bytes,0,l_bytes2,0,l_bytesRead);
- setBytes(parameterIndex, l_bytes2);
- }
- } else {
- //Version 7.1 only supported streams for LargeObjects
- //but the jdbc spec indicates that streams should be
- //available for LONGVARBINARY instead
- LargeObjectManager lom = connection.getLargeObjectAPI();
- int oid = lom.create();
- LargeObject lob = lom.open(oid);
- OutputStream los = lob.getOutputStream();
- try {
- // could be buffered, but then the OutputStream returned by LargeObject
- // is buffered internally anyhow, so there would be no performance
- // boost gained, if anything it would be worse!
- int c=x.read();
- int p=0;
- while(c>-1 && p<length) {
- los.write(c);
- c=x.read();
- p++;
- }
- los.close();
- } catch(IOException se) {
- throw new PSQLException("postgresql.unusual",se);
- }
- // lob is closed by the stream so don't call lob.close()
- setInt(parameterIndex,oid);
- }
+ if (connection.haveMinimumCompatibleVersion("7.2"))
+ {
+ //Version 7.2 supports BinaryStream for for the PG bytea type
+ //As the spec/javadoc for this method indicate this is to be used for
+ //large binary values (i.e. LONGVARBINARY) PG doesn't have a separate
+ //long binary datatype, but with toast the bytea datatype is capable of
+ //handling very large values. Thus the implementation ends up calling
+ //setBytes() since there is no current way to stream the value to the server
+ byte[] l_bytes = new byte[length];
+ int l_bytesRead;
+ try
+ {
+ l_bytesRead = x.read(l_bytes, 0, length);
+ }
+ catch (IOException l_ioe)
+ {
+ throw new PSQLException("postgresql.unusual", l_ioe);
+ }
+ if (l_bytesRead == length)
+ {
+ setBytes(parameterIndex, l_bytes);
+ }
+ else
+ {
+ //the stream contained less data than they said
+ byte[] l_bytes2 = new byte[l_bytesRead];
+ System.arraycopy(l_bytes, 0, l_bytes2, 0, l_bytesRead);
+ setBytes(parameterIndex, l_bytes2);
+ }
+ }
+ else
+ {
+ //Version 7.1 only supported streams for LargeObjects
+ //but the jdbc spec indicates that streams should be
+ //available for LONGVARBINARY instead
+ LargeObjectManager lom = connection.getLargeObjectAPI();
+ int oid = lom.create();
+ LargeObject lob = lom.open(oid);
+ OutputStream los = lob.getOutputStream();
+ try
+ {
+ // could be buffered, but then the OutputStream returned by LargeObject
+ // is buffered internally anyhow, so there would be no performance
+ // boost gained, if anything it would be worse!
+ int c = x.read();
+ int p = 0;
+ while (c > -1 && p < length)
+ {
+ los.write(c);
+ c = x.read();
+ p++;
+ }
+ los.close();
+ }
+ catch (IOException se)
+ {
+ throw new PSQLException("postgresql.unusual", se);
+ }
+ // lob is closed by the stream so don't call lob.close()
+ setInt(parameterIndex, oid);
+ }
}
/**
* In general, parameter values remain in force for repeated used of a
* Statement. Setting a parameter value automatically clears its
- * previous value. However, in coms cases, it is useful to immediately
+ * previous value. However, in coms cases, it is useful to immediately
* release the resources used by the current parameter values; this
* can be done by calling clearParameters
*
@@ -559,62 +604,66 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
* @param x the object containing the input parameter value
* @param targetSqlType The SQL type to be send to the database
* @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC
- * * types this is the number of digits after the decimal. For
- * * all other types this value will be ignored.
+ * * types this is the number of digits after the decimal. For
+ * * all other types this value will be ignored.
* @exception SQLException if a database access error occurs
*/
public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException
{
- if (x == null){
- setNull(parameterIndex,Types.OTHER);
- return;
+ if (x == null)
+ {
+ setNull(parameterIndex, Types.OTHER);
+ return ;
}
switch (targetSqlType)
{
- case Types.TINYINT:
- case Types.SMALLINT:
- case Types.INTEGER:
- case Types.BIGINT:
- case Types.REAL:
- case Types.FLOAT:
- case Types.DOUBLE:
- case Types.DECIMAL:
- case Types.NUMERIC:
- if (x instanceof Boolean)
- set(parameterIndex, ((Boolean)x).booleanValue() ? "1" : "0");
- else
- set(parameterIndex, x.toString());
- break;
- case Types.CHAR:
- case Types.VARCHAR:
- case Types.LONGVARCHAR:
- setString(parameterIndex, x.toString());
- break;
- case Types.DATE:
- setDate(parameterIndex, (java.sql.Date)x);
- break;
- case Types.TIME:
- setTime(parameterIndex, (Time)x);
- break;
- case Types.TIMESTAMP:
- setTimestamp(parameterIndex, (Timestamp)x);
- break;
- case Types.BIT:
- if (x instanceof Boolean) {
- set(parameterIndex, ((Boolean)x).booleanValue() ? "TRUE" : "FALSE");
- } else {
- throw new PSQLException("postgresql.prep.type");
- }
- break;
- case Types.BINARY:
- case Types.VARBINARY:
- setObject(parameterIndex,x);
- break;
- case Types.OTHER:
- setString(parameterIndex, ((PGobject)x).getValue());
- break;
- default:
+ case Types.TINYINT:
+ case Types.SMALLINT:
+ case Types.INTEGER:
+ case Types.BIGINT:
+ case Types.REAL:
+ case Types.FLOAT:
+ case Types.DOUBLE:
+ case Types.DECIMAL:
+ case Types.NUMERIC:
+ if (x instanceof Boolean)
+ set(parameterIndex, ((Boolean)x).booleanValue() ? "1" : "0");
+ else
+ set(parameterIndex, x.toString());
+ break;
+ case Types.CHAR:
+ case Types.VARCHAR:
+ case Types.LONGVARCHAR:
+ setString(parameterIndex, x.toString());
+ break;
+ case Types.DATE:
+ setDate(parameterIndex, (java.sql.Date)x);
+ break;
+ case Types.TIME:
+ setTime(parameterIndex, (Time)x);
+ break;
+ case Types.TIMESTAMP:
+ setTimestamp(parameterIndex, (Timestamp)x);
+ break;
+ case Types.BIT:
+ if (x instanceof Boolean)
+ {
+ set(parameterIndex, ((Boolean)x).booleanValue() ? "TRUE" : "FALSE");
+ }
+ else
+ {
throw new PSQLException("postgresql.prep.type");
+ }
+ break;
+ case Types.BINARY:
+ case Types.VARBINARY:
+ setObject(parameterIndex, x);
+ break;
+ case Types.OTHER:
+ setString(parameterIndex, ((PGobject)x).getValue());
+ break;
+ default:
+ throw new PSQLException("postgresql.prep.type");
}
}
@@ -622,18 +671,19 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
{
setObject(parameterIndex, x, targetSqlType, 0);
}
-
- /**
- * This stores an Object into a parameter.
- * <p>New for 6.4, if the object is not recognised, but it is
- * Serializable, then the object is serialised using the
- * org.postgresql.util.Serialize class.
- */
+
+ /**
+ * This stores an Object into a parameter.
+ * <p>New for 6.4, if the object is not recognised, but it is
+ * Serializable, then the object is serialised using the
+ * org.postgresql.util.Serialize class.
+ */
public void setObject(int parameterIndex, Object x) throws SQLException
{
- if (x == null){
- setNull(parameterIndex,Types.OTHER);
- return;
+ if (x == null)
+ {
+ setNull(parameterIndex, Types.OTHER);
+ return ;
}
if (x instanceof String)
setString(parameterIndex, (String)x);
@@ -667,11 +717,11 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
/**
* Some prepared statements return multiple results; the execute method
- * handles these complex statements as well as the simpler form of
+ * handles these complex statements as well as the simpler form of
* statements handled by executeQuery and executeUpdate
*
* @return true if the next result is a ResultSet; false if it is an
- * * update count or there are no more results
+ * * update count or there are no more results
* @exception SQLException if a database access error occurs
*/
public boolean execute() throws SQLException
@@ -682,19 +732,20 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
for (i = 0 ; i < inStrings.length ; ++i)
{
if (inStrings[i] == null)
- throw new PSQLException("postgresql.prep.param",new Integer(i + 1));
+ throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
s.append (templateStrings[i]);
s.append (inStrings[i]);
}
s.append(templateStrings[inStrings.length]);
- return super.execute(s.toString()); // in Statement class
+ return super.execute(s.toString()); // in Statement class
}
/**
* Returns the SQL statement with the current template values
* substituted.
*/
- public String toString() {
+ public String toString()
+ {
StringBuffer s = new StringBuffer();
int i;
@@ -709,14 +760,14 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
s.append(templateStrings[inStrings.length]);
return s.toString();
}
-
+
// **************************************************************
- // END OF PUBLIC INTERFACE
+ // END OF PUBLIC INTERFACE
// **************************************************************
-
+
/**
* There are a lot of setXXX classes which all basically do
- * the same thing. We need a method which actually does the
+ * the same thing. We need a method which actually does the
* set for us.
*
* @param paramIndex the index into the inString
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java
index fe01d15e294..bbde9d5bf91 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java
@@ -21,13 +21,13 @@ import org.postgresql.core.Encoding;
* Statement. The table rows are retrieved in sequence. Within a row its
* column values can be accessed in any order.
*
- * <P>A ResultSet maintains a cursor pointing to its current row of data.
+ * <P>A ResultSet maintains a cursor pointing to its current row of data.
* Initially the cursor is positioned before the first row. The 'next'
* method moves the cursor to the next row.
*
* <P>The getXXX methods retrieve column values for the current row. You can
* retrieve values either using the index number of the column, or by using
- * the name of the column. In general using the column index will be more
+ * the name of the column. In general using the column index will be more
* efficient. Columns are numbered from 1.
*
* <P>For maximum portability, ResultSet columns within each row should be read
@@ -40,15 +40,15 @@ import org.postgresql.core.Encoding;
*
* <P>Column names used as input to getXXX methods are case insenstive. When
* performing a getXXX using a column name, if several columns have the same
- * name, then the value of the first matching column will be returned. The
+ * name, then the value of the first matching column will be returned. The
* column name option is designed to be used when column names are used in the
* SQL Query. For columns that are NOT explicitly named in the query, it is
- * best to use column numbers. If column names were used there is no way for
+ * best to use column numbers. If column names were used there is no way for
* the programmer to guarentee that they actually refer to the intended
* columns.
*
- * <P>A ResultSet is automatically closed by the Statement that generated it
- * when that Statement is closed, re-executed, or is used to retrieve the
+ * <P>A ResultSet is automatically closed by the Statement that generated it
+ * when that Statement is closed, re-executed, or is used to retrieve the
* next result from a sequence of multiple results.
*
* <P>The number, types and properties of a ResultSet's columns are provided by
@@ -57,859 +57,932 @@ import org.postgresql.core.Encoding;
* @see ResultSetMetaData
* @see java.sql.ResultSet
*/
-public class ResultSet extends org.postgresql.ResultSet implements java.sql.ResultSet
+public class ResultSet extends org.postgresql.ResultSet implements java.sql.ResultSet
{
- /**
- * Create a new ResultSet - Note that we create ResultSets to
- * represent the results of everything.
- *
- * @param fields an array of Field objects (basically, the
- * ResultSet MetaData)
- * @param tuples Vector of the actual data
- * @param status the status string returned from the back end
- * @param updateCount the number of rows affected by the operation
- * @param cursor the positioned update/delete cursor name
- */
- public ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount, int insertOID, boolean binaryCursor)
- {
- super(conn,fields,tuples,status,updateCount,insertOID,binaryCursor);
- }
-
- /**
- * Create a new ResultSet - Note that we create ResultSets to
- * represent the results of everything.
- *
- * @param fields an array of Field objects (basically, the
- * ResultSet MetaData)
- * @param tuples Vector of the actual data
- * @param status the status string returned from the back end
- * @param updateCount the number of rows affected by the operation
- * @param cursor the positioned update/delete cursor name
- */
- public ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount)
- {
- super(conn,fields,tuples,status,updateCount,0,false);
- }
-
- /**
- * A ResultSet is initially positioned before its first row,
- * the first call to next makes the first row the current row;
- * the second call makes the second row the current row, etc.
- *
- * <p>If an input stream from the previous row is open, it is
- * implicitly closed. The ResultSet's warning chain is cleared
- * when a new row is read
- *
- * @return true if the new current is valid; false if there are no
- * more rows
- * @exception SQLException if a database access error occurs
- */
- public boolean next() throws SQLException
- {
- if (++current_row >= rows.size())
- return false;
- this_row = (byte [][])rows.elementAt(current_row);
- return true;
- }
-
- /**
- * In some cases, it is desirable to immediately release a ResultSet
- * database and JDBC resources instead of waiting for this to happen
- * when it is automatically closed. The close method provides this
- * immediate release.