Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
ff246d7b
Commit
ff246d7b
authored
Aug 16, 1997
by
Marc G. Fournier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bring in Adrian's JDBC driver as an interface
parent
fd86ae15
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
5097 additions
and
0 deletions
+5097
-0
src/interfaces/jdbc/JDBC_Test.java
src/interfaces/jdbc/JDBC_Test.java
+61
-0
src/interfaces/jdbc/postgresql/CallableStatement.java
src/interfaces/jdbc/postgresql/CallableStatement.java
+126
-0
src/interfaces/jdbc/postgresql/Connection.java
src/interfaces/jdbc/postgresql/Connection.java
+847
-0
src/interfaces/jdbc/postgresql/DatabaseMetaData.java
src/interfaces/jdbc/postgresql/DatabaseMetaData.java
+1556
-0
src/interfaces/jdbc/postgresql/Driver.java
src/interfaces/jdbc/postgresql/Driver.java
+269
-0
src/interfaces/jdbc/postgresql/Field.java
src/interfaces/jdbc/postgresql/Field.java
+89
-0
src/interfaces/jdbc/postgresql/PG_Object.java
src/interfaces/jdbc/postgresql/PG_Object.java
+31
-0
src/interfaces/jdbc/postgresql/PreparedStatement.java
src/interfaces/jdbc/postgresql/PreparedStatement.java
+538
-0
src/interfaces/jdbc/postgresql/ResultSet.java
src/interfaces/jdbc/postgresql/ResultSet.java
+845
-0
src/interfaces/jdbc/postgresql/ResultSetMetaData.java
src/interfaces/jdbc/postgresql/ResultSetMetaData.java
+429
-0
src/interfaces/jdbc/postgresql/Statement.java
src/interfaces/jdbc/postgresql/Statement.java
+306
-0
No files found.
src/interfaces/jdbc/JDBC_Test.java
0 → 100644
View file @
ff246d7b
import
java.io.*
;
import
java.lang.*
;
import
java.sql.*
;
class
JDBC_Test
{
public
JDBC_Test
()
{
}
public
static
void
main
(
String
argv
[])
{
String
url
=
new
String
(
argv
[
0
]);
Connection
db
;
Statement
s
;
ResultSet
rs
;
// Load the driver
try
{
Class
.
forName
(
"postgresql.Driver"
);
}
catch
(
ClassNotFoundException
e
)
{
System
.
err
.
println
(
"Exception: "
+
e
.
toString
());
}
// Lets do a few things -- it doesn't do everything, but
// it tests out basic functionality
try
{
System
.
out
.
println
(
"Connecting to Database URL = "
+
url
);
db
=
DriverManager
.
getConnection
(
url
,
"adrian"
,
""
);
System
.
out
.
println
(
"Connected...Now creating a statement"
);
s
=
db
.
createStatement
();
System
.
out
.
println
(
"Ok...now we will create a table"
);
s
.
executeUpdate
(
"create table test (a int2, b int2)"
);
System
.
out
.
println
(
"Now we will insert some columns"
);
s
.
executeUpdate
(
"insert into test values (1, 1)"
);
s
.
executeUpdate
(
"insert into test values (2, 1)"
);
s
.
executeUpdate
(
"insert into test values (3, 1)"
);
System
.
out
.
println
(
"Inserted some data"
);
System
.
out
.
println
(
"Now lets try a select"
);
rs
=
s
.
executeQuery
(
"select a, b from test"
);
System
.
out
.
println
(
"Back from the select...the following are results"
);
int
i
=
0
;
while
(
rs
.
next
())
{
int
a
=
rs
.
getInt
(
"a"
);
int
b
=
rs
.
getInt
(
"b"
);
System
.
out
.
println
(
"row "
+
i
+
" "
+
a
+
" "
+
b
);
i
++;
}
System
.
out
.
println
(
"Ok...dropping the table"
);
s
.
executeUpdate
(
"drop table test"
);
System
.
out
.
println
(
"Now closing the connection"
);
s
.
close
();
db
.
close
();
}
catch
(
SQLException
e
)
{
System
.
out
.
println
(
"Exception: "
+
e
.
toString
());
}
}
}
src/interfaces/jdbc/postgresql/CallableStatement.java
0 → 100644
View file @
ff246d7b
package
postgresql
;
import
java.math.*
;
import
java.sql.*
;
/**
* @version 1.0 15-APR-1997
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
*
* CallableStatement is used to execute SQL stored procedures.
*
* JDBC provides a stored procedure SQL escape that allows stored procedures
* to be called in a standard way for all RDBMS's. This escape syntax has
* one form that includes a result parameter and one that does not. If used,
* the result parameter must be generated as an OUT parameter. The other
* parameters may be used for input, output or both. Parameters are refered
* to sequentially, by number. The first parameter is 1.
*
* <PRE>
* {?= call <procedure-name>[<arg1>,<arg2>, ...]}
* {call <procedure-name>[<arg1>,<arg2>, ...]}
* </PRE>
*
* IN parameters are set using the set methods inherited from
* PreparedStatement. The type of all OUT parameters must be registered
* prior to executing the stored procedure; their values are retrieved
* after execution via the get methods provided here.
*
* A CallableStatement may return a ResultSet or multiple ResultSets. Multiple
* ResultSets are handled using operations inherited from Statement.
*
* For maximum portability, a call's ResultSets and update counts should be
* processed prior to getting the values of output parameters.
*
* @see java.sql.Connection#prepareCall
* @see java.sql.ResultSet
* @see java.sql.CallableStatement
*/
public
class
CallableStatement
implements
java
.
sql
.
CallableStatement
{
public
void
registerOutParameter
(
int
paramterIndex
,
int
sqlType
)
throws
SQLException
{
// XXX-Not Implemented
}
public
void
registerOutParameter
(
int
parameterIndex
,
int
sqlType
,
int
scale
)
throws
SQLException
{
// XXX-Not Implemented
}
public
boolean
wasNull
()
throws
SQLException
{
// XXX-Not Implemented
}
public
String
getString
(
int
parameterIndex
)
throws
SQLException
{
// XXX-Not Implemented
}
public
boolean
getBoolean
(
int
parameterIndex
)
throws
SQLException
{
// XXX-Not Implemented
}
public
byte
getByte
(
int
parameterIndex
)
throws
SQLException
{
// XXX-Not Implemented
}
public
short
getShort
(
int
parameterIndex
)
throws
SQLException
{
// XXX-Not Implemented
}
public
int
getInt
(
int
parameterIndex
)
throws
SQLException
{
// XXX-Not Implemented
}
public
long
getLong
(
int
parameterIndex
)
throws
SQLException
{
// XXX-Not Implemented
}
public
float
getFloat
(
int
parameterIndex
)
throws
SQLException
{
// XXX-Not Implemented
}
public
double
getDouble
(
int
parameterIndex
)
throws
SQLException
{
// XXX-Not Implemented
}
public
BigDecimal
getBigDecimal
(
int
parameterIndex
,
int
scale
)
throws
SQLException
{
// XXX-Not Implemented
}
public
byte
[]
getBytes
(
int
parameterIndex
)
throws
SQLException
{
// XXX-Not Implemented
}
public
Date
getDate
(
int
parameterIndex
)
throws
SQLException
{
// XXX-Not Implemented
}
public
Time
getTime
(
int
parameterIndex
)
throws
SQLException
{
// XXX-Not Implemented
}
public
Timestamp
getTimestamp
(
int
parameterIndex
)
throws
SQLException
{
// XXX-Not Implemented
}
public
Object
getObject
(
int
parameterIndex
)
throws
SQLException
{
// XXX-Not Implemented
}
}
src/interfaces/jdbc/postgresql/Connection.java
0 → 100644
View file @
ff246d7b
package
postgresql
;
import
java.io.*
;
import
java.lang.*
;
import
java.net.*
;
import
java.util.*
;
import
java.sql.*
;
import
postgresql.*
;
/**
* @version 1.0 15-APR-1997
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
*
* A Connection represents a session with a specific database. Within the
* context of a Connection, SQL statements are executed and results are
* returned.
*
* 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 obtained
* with the getMetaData method.
*
* <B>Note:</B> By default, the Connection automatically commits changes
* 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
implements
java
.
sql
.
Connection
{
private
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
;
public
boolean
CONNECTION_OK
=
true
;
public
boolean
CONNECTION_BAD
=
false
;
private
int
STARTUP_CODE
=
7
;
private
boolean
autoCommit
=
true
;
private
boolean
readOnly
=
false
;
private
Driver
this_driver
;
private
String
this_url
;
private
String
cursor
=
null
;
// The positioned update cursor name
/**
* Connect to a PostgreSQL database back end.
*
* @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
*/
public
Connection
(
String
host
,
int
port
,
Properties
info
,
String
database
,
String
url
,
Driver
d
)
throws
SQLException
{
int
len
=
288
;
// Length of a startup packet
this_driver
=
d
;
this_url
=
new
String
(
url
);
PG_DATABASE
=
new
String
(
database
);
PG_PASSWORD
=
new
String
(
info
.
getProperty
(
"password"
));
PG_USER
=
new
String
(
info
.
getProperty
(
"user"
));
PG_PORT
=
port
;
PG_HOST
=
new
String
(
host
);
PG_STATUS
=
CONNECTION_BAD
;
try
{
pg_stream
=
new
PG_Stream
(
host
,
port
);
}
catch
(
IOException
e
)
{
throw
new
SQLException
(
"Connection failed: "
+
e
.
toString
());
}
// Now we need to construct and send a startup packet
try
{
pg_stream
.
SendInteger
(
len
,
4
);
len
-=
4
;
pg_stream
.
SendInteger
(
STARTUP_CODE
,
4
);
len
-=
4
;
pg_stream
.
Send
(
database
.
getBytes
(),
64
);
len
-=
64
;
pg_stream
.
Send
(
PG_USER
.
getBytes
(),
len
);
}
catch
(
IOException
e
)
{
throw
new
SQLException
(
"Connection failed: "
+
e
.
toString
());
}
ExecSQL
(
" "
);
// Test connection
PG_STATUS
=
CONNECTION_OK
;
}
/**
* 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
SQLException
(
"Callable Statements are not supported at this time"
);
// return new CallableStatement(this, sql);
}
/**
* 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
;
}
/**
* 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
ExecSQL
(
"begin"
);
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
;
ExecSQL
(
"commit"
);
autoCommit
=
true
;
ExecSQL
(
"begin"
);
autoCommit
=
false
;
}
/**
* 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
;
ExecSQL
(
"rollback"
);
autoCommit
=
true
;
ExecSQL
(
"begin"
);
autoCommit
=
false
;
}
/**
* 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
.
close
();
}
catch
(
IOException
e
)
{}
pg_stream
=
null
;
}
}
/**
* 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
{
// return new DatabaseMetaData(this);
throw
new
SQLException
(
"DatabaseMetaData not supported"
);
}
/**
* 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
;
}
/**
* 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
null
;
}
/**
* 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
{
throw
new
SQLException
(
"Transaction Isolation Levels are not implemented"
);
}
/**
* 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
{
return
java
.
sql
.
Connection
.
TRANSACTION_SERIALIZABLE
;
}
/**
* 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
null
;
// We handle warnings as errors
}
/**
* 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
{
// Not handles since we handle wanrings as errors
}
// **********************************************************
// END OF PUBLIC INTERFACE
// **********************************************************
/**
* 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
synchronized
ResultSet
ExecSQL
(
String
sql
)
throws
SQLException
{
Field
[]
fields
=
null
;
Vector
tuples
=
new
Vector
();
byte
[]
buf
=
new
byte
[
sql
.
length
()];
int
fqp
=
0
;
boolean
hfr
=
false
;
String
recv_status
=
null
,
msg
;
SQLException
final_error
=
null
;
if
(
sql
.
length
()
>
8192
)
throw
new
SQLException
(
"SQL Statement too long: "
+
sql
);
try
{
pg_stream
.
SendChar
(
'Q'
);
buf
=
sql
.
getBytes
();
pg_stream
.
Send
(
buf
);
pg_stream
.
SendChar
(
0
);
}
catch
(
IOException
e
)
{
throw
new
SQLException
(
"I/O Error: "
+
e
.
toString
());
}
while
(!
hfr
||
fqp
>
0
)
{
int
c
=
pg_stream
.
ReceiveChar
();
switch
(
c
)
{
case
'A'
:
// Asynchronous Notify
int
pid
=
pg_stream
.
ReceiveInteger
(
4
);
msg
=
pg_stream
.
ReceiveString
(
8192
);
break
;
case
'B'
:
// Binary Data Transfer
if
(
fields
==
null
)
throw
new
SQLException
(
"Tuple received before MetaData"
);
tuples
.
addElement
(
pg_stream
.
ReceiveTuple
(
fields
.
length
,
true
));
break
;
case
'C'
:
// Command Status
recv_status
=
pg_stream
.
ReceiveString
(
8192
);
if
(
fields
!=
null
)
hfr
=
true
;
else
{
try
{
pg_stream
.
SendChar
(
'Q'
);
pg_stream
.
SendChar
(
' '
);
pg_stream
.
SendChar
(
0
);
}
catch
(
IOException
e
)
{
throw
new
SQLException
(
"I/O Error: "
+
e
.
toString
());
}
fqp
++;
}
break
;
case
'D'
:
// Text Data Transfer
if
(
fields
==
null
)
throw
new
SQLException
(
"Tuple received before MetaData"
);
tuples
.
addElement
(
pg_stream
.
ReceiveTuple
(
fields
.
length
,
false
));
break
;
case
'E'
:
// Error Message
msg
=
pg_stream
.
ReceiveString
(
4096
);
final_error
=
new
SQLException
(
msg
);
hfr
=
true
;
break
;
case
'I'
:
// Empty Query
int
t
=
pg_stream
.
ReceiveChar
();
if
(
t
!=
0
)
throw
new
SQLException
(
"Garbled Data"
);
if
(
fqp
>
0
)
fqp
--;
if
(
fqp
==
0
)
hfr
=
true
;
break
;
case
'N'
:
// Error Notification
msg
=
pg_stream
.
ReceiveString
(
4096
);
PrintStream
log
=
DriverManager
.
getLogStream
();
log
.
println
(
msg
);
break
;
case
'P'
:
// Portal Name
String
pname
=
pg_stream
.
ReceiveString
(
8192
);
break
;
case
'T'
:
// MetaData Field Description
if
(
fields
!=
null
)
throw
new
SQLException
(
"Cannot handle multiple result groups"
);
fields
=
ReceiveFields
();
break
;
default
:
throw
new
SQLException
(
"Unknown Response Type: "
+
(
char
)
c
);
}
}
if
(
final_error
!=
null
)
throw
final_error
;
return
new
ResultSet
(
this
,
fields
,
tuples
,
recv_status
,
1
);
}
/**
* Receive the field descriptions from the back end
*
* @return an array of the Field object describing the fields
* @exception SQLException if a database error occurs
*/
private
Field
[]
ReceiveFields
()
throws
SQLException
{
int
nf
=
pg_stream
.
ReceiveInteger
(
2
),
i
;
Field
[]
fields
=
new
Field
[
nf
];
for
(
i
=
0
;
i
<
nf
;
++
i
)
{
String
typname
=
pg_stream
.
ReceiveString
(
8192
);
int
typid
=
pg_stream
.
ReceiveInteger
(
4
);
int
typlen
=
pg_stream
.
ReceiveInteger
(
2
);
fields
[
i
]
=
new
Field
(
this
,
typname
,
typid
,
typlen
);
}
return
fields
;
}
/**
* 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
;
}
}
// ***********************************************************************
// This class handles all the Streamed I/O for a postgresql connection
class
PG_Stream
{
private
Socket
connection
;
private
InputStream
pg_input
;
private
OutputStream
pg_output
;
/**
* 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
);
pg_input
=
connection
.
getInputStream
();
pg_output
=
connection
.
getOutputStream
();
}
/**
* 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
(
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
=
new
byte
[
siz
];
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 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
{
int
i
;
pg_output
.
write
(
buf
,
0
,
(
buf
.
length
<
siz
?
buf
.
length
:
siz
));
if
(
buf
.
length
<
siz
)
{
for
(
i
=
buf
.
length
;
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
;
try
{
c
=
pg_input
.
read
();
if
(
c
<
0
)
throw
new
IOException
(
"EOF"
);
}
catch
(
IOException
e
)
{
throw
new
SQLException
(
"Error reading from backend: "
+
e
.
toString
());
}
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
;
try
{
for
(
int
i
=
0
;
i
<
siz
;
i
++)
{
int
b
=
pg_input
.
read
();
if
(
b
<
0
)
throw
new
IOException
(
"EOF"
);
n
=
n
|
(
b
>>
(
8
*
i
))
;
}
}
catch
(
IOException
e
)
{
throw
new
SQLException
(
"Error reading from backend: "
+
e
.
toString
());
}
return
n
;
}
/**
* Receives a null-terminated string from the backend. Maximum of
* maxsiz bytes - if we don't see a null, then we assume something
* has gone wrong.
*
* @param maxsiz maximum length of string
* @return string from back end
* @exception SQLException if an I/O error occurs
*/
public
String
ReceiveString
(
int
maxsiz
)
throws
SQLException
{
byte
[]
rst
=
new
byte
[
maxsiz
];
int
s
=
0
;
try
{
while
(
s
<
maxsiz
)
{
int
c
=
pg_input
.
read
();
if
(
c
<
0
)
throw
new
IOException
(
"EOF"
);
else
if
(
c
==
0
)
break
;
else
rst
[
s
++]
=
(
byte
)
c
;
}
if
(
s
>=
maxsiz
)
throw
new
IOException
(
"Too Much Data"
);
}
catch
(
IOException
e
)
{
throw
new
SQLException
(
"Error reading from backend: "
+
e
.
toString
());
}
String
v
=
new
String
(
rst
,
0
,
s
);
return
v
;
}
/**
* 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
=
new
byte
[
nf
][
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
=
ReceiveInteger
(
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
=
new
byte
[
siz
];
int
s
=
0
;
try
{
while
(
s
<
siz
)
{
int
w
=
pg_input
.
read
(
answer
,
s
,
siz
-
s
);
if
(
w
<
0
)
throw
new
IOException
(
"EOF"
);
s
+=
w
;
}
}
catch
(
IOException
e
)
{
throw
new
SQLException
(
"Error reading from backend: "
+
e
.
toString
());
}
return
answer
;
}
/**
* Closes the connection
*
* @exception IOException if a IO Error occurs
*/
public
void
close
()
throws
IOException
{
pg_output
.
close
();
pg_input
.
close
();
connection
.
close
();
}
}
src/interfaces/jdbc/postgresql/DatabaseMetaData.java
0 → 100644
View file @
ff246d7b
package
postgresql
;
import
java.sql.*
;
/**
* @version 1.0 15-APR-1997
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
*
* This class provides information about the database as a whole.
*
* Many of the methods here return lists of information in ResultSets. You
* can use the normal ResultSet methods such as getString and getInt to
* retrieve the data from these ResultSets. If a given form of metadata is
* not available, these methods should throw a SQLException.
*
* Some of these methods take arguments that are String patterns. These
* arguments all have names such as fooPattern. Within a pattern String,
* "%" means match any substring of 0 or more characters, and "_" means
* match any one character. Only metadata entries matching the search
* pattern are returned. if a search pattern argument is set to a null
* ref, it means that argument's criteria should be dropped from the
* search.
*
* A SQLException will be throws if a driver does not support a meta
* data method. In the case of methods that return a ResultSet, either
* a ResultSet (which may be empty) is returned or a SQLException is
* thrown.
*
* @see java.sql.DatabaseMetaData
*/
public
class
DatabaseMetaData
implements
java
.
sql
.
DatabaseMetaData
{
Connection
connection
;
// The connection association
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
false
;
}
/**
* 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
true
;
}
/**
* 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
new
String
(
"PostgreSQL"
);
}
/**
* What is the version of this database product. Note that
* PostgreSQL 6.1 has a system catalog called pg_version -
* however, select * from pg_version on any database retrieves
* no rows. For now, we will return the version 6.1 (in the
* hopes that we change this driver as often as we change the
* database)
*
* @return the database version
* @exception SQLException if a database access error occurs
*/
public
String
getDatabaseProductVersion
()
throws
SQLException
{
return
(
"6.1"
);
}
/**
* 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
new
String
(
"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
new
String
(
"1.0"
);
}
/**
* What is this JDBC driver's major version number?
*
* @return the JDBC driver major version
*/
public
int
getDriverMajorVersion
()
{
return
1
;
}
/**
* What is this JDBC driver's minor version number?
*
* @return the JDBC driver minor version
*/
public
int
getDriverMinorVersion
()
{
return
0
;
}
/**
* 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.
*
* 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
true
;
}
/**
* 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
false
;
}
/**
* 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.
*
* 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
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.
*
* If an SQL identifier is a table name, column name, etc. then
* we do not support it.
*
* @return the quoting string
* @exception SQLException if a database access error occurs
*/
public
String
getIdentifierQuoteString
()
throws
SQLException
{
return
new
String
(
" "
);
}
/**
* Get a comma separated list of all a database's SQL keywords that
* are NOT also SQL92 keywords.
*
* Within PostgreSQL, the keywords are found in
* src/backend/parser/keywords.c
* For SQL Keywords, I took the list provided at
* http://web.dementia.org/~shadow/sql/sql3bnf.sep93.txt
* 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
new
String
(
"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
}
public
String
getStringFunctions
()
throws
SQLException
{
// XXX-Not Implemented
}
public
String
getSystemFunctions
()
throws
SQLException
{
// XXX-Not Implemented
}
public
String
getTimeDateFunctions
()
throws
SQLException
{
// XXX-Not Implemented
}
/**
* 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
new
String
(
"\\"
);
}
/**
* Get all the "extra" characters that can bew used in unquoted
* identifier names (those beyond a-zA-Z0-9 and _)
*
* 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
new
String
(
""
);
}
/**
* 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?
* Yes for PostgreSQL 6.1
*
* @return true if so
* @exception SQLException if a database access error occurs
*/
public
boolean
supportsAlterTableWithDropColumn
()
throws
SQLException
{
return
true
;
}
/**
* Is column aliasing supported?
*
* 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.
*
* e.g.
*
* select count(C) as C_COUNT from T group by C;
*
* 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
}
public
boolean
supportsConvert
(
int
fromType
,
int
toType
)
throws
SQLException
{
// XXX-Not Implemented
}
public
boolean
supportsTableCorrelationNames
()
throws
SQLException
{
// XXX-Not Implemented
}
public
boolean
supportsDifferentTableCorrelationNames
()
throws
SQLException
{
// XXX-Not Implemented
}
/**
* Are expressions in "ORCER BY" lists supported?
*
* 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
false
;
}
/**
* Can an "ORDER BY" clause use columns not in the SELECT?
* I checked it, and you can't.
*
* @return true if so
* @exception SQLException if a database access error occurs
*/
public
boolean
supportsOrderByUnrelated
()
throws
SQLException
{
return
false
;
}
/**
* 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?
* I checked it - it seems to allow it
*
* @return true if so
* @exception SQLException if a database access error occurs
*/
public
boolean
supportsGroupByUnrelated
()
throws
SQLException
{
return
true
;
}
/**
* 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?
*
* @return true if so
* @exception SQLException if a database access error occurs
*/
public
boolean
supportsGroupByBeyondSelect
()
throws
SQLException
{
return
true
;
// For now...
}
/**
* 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
true
;
}
/**
* 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. We dont support NOT NULL, so we are not
* JDBC compliant.
*
* @return true if so
* @exception SQLException if a database access error occurs
*/
public
boolean
supportsNonNullableColumns
()
throws
SQLException
{
return
false
;
}
/**
* Does this driver support the minimum ODBC SQL grammar. This
* grammar is defined at:
*
* http://www.microsoft.com/msdn/sdk/platforms/doc/odbc/src/intropr.htm
*
* 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. I think we have
* to support outer joins for this to be 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? Anyone who does not support Entry level cannot support
* Intermediate level.
*
* @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? From my knowledge, nope.
*
* @return true if so
* @exception SQLException if a database access error occurs
*/
public
boolean
supportsOuterJoins
()
throws
SQLException
{
return
false
;
}
/**
* Are full nexted outer joins supported? Well, we dont support any
* form of outer join, so this is no as well
*
* @return true if so
* @exception SQLException if a database access error occurs
*/
public
boolean
supportsFullOuterJoins
()
throws
SQLException
{
return
false
;
}
/**
* Is there limited support for outer joins? (This will be true if
* supportFullOuterJoins is true)
*
* @return true if so
* @exception SQLException if a database access error occurs
*/
public
boolean
supportsLimitedOuterJoins
()
throws
SQLException
{
return
false
;
}
/**
* What is the database vendor's preferred term for "schema" - well,
* we do not provide support for schemas, so lets just use that
* term.
*
* @return the vendor term
* @exception SQLException if a database access error occurs
*/
public
String
getSchemaTerm
()
throws
SQLException
{
return
new
String
(
"Schema"
);
}
/**
* What is the database vendor's preferred term for "procedure" -
* I kind of like "Procedure" myself.
*
* @return the vendor term
* @exception SQLException if a database access error occurs
*/
public
String
getProcedureTerm
()
throws
SQLException
{
return
new
String
(
"Procedure"
);
}
/**
* What is the database vendor's preferred term for "catalog"? -
* we dont have a preferred term, so just use Catalog
*
* @return the vendor term
* @exception SQLException if a database access error occurs
*/
public
String
getCatalogTerm
()
throws
SQLException
{
return
new
String
(
"Catalog"
);
}
/**
* 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
{
return
false
;
}
/**
* What is the Catalog separator. Hmmm....well, I kind of like
* a period (so we get catalog.table definitions). - I don't think
* PostgreSQL supports catalogs anyhow, so it makes no difference.
*
* @return the catalog separator string
* @exception SQLException if a database access error occurs
*/
public
String
getCatalogSeparator
()
throws
SQLException
{
return
new
String
(
"."
);
}
/**
* 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...
}
public
boolean
supportsSelectForUpdate
()
throws
SQLException
{
// XXX-Not Implemented
}
public
boolean
supportsStoredProcedures
()
throws
SQLException
{
// XXX-Not Implemented
}
public
boolean
supportsSubqueriesInComparisons
()
throws
SQLException
{
// XXX-Not Implemented
}
public
boolean
supportsSubqueriesInExists
()
throws
SQLException
{
// XXX-Not Implemented
}
public
boolean
supportsSubqueriesInIns
()
throws
SQLException
{
// XXX-Not Implemented
}
public
boolean
supportsSubqueriesInQuantifieds
()
throws
SQLException
{
// XXX-Not Implemented
}
public
boolean
supportsCorrelatedSubqueries
()
throws
SQLException
{
// XXX-Not Implemented
}
/**
* Is SQL UNION supported? Nope.
*
* @return true if so
* @exception SQLException if a database access error occurs
*/
public
boolean
supportsUnion
()
throws
SQLException
{
return
false
;
}
/**
* Is SQL UNION ALL supported? Nope.
*
* @return true if so
* @exception SQLException if a database access error occurs
*/
public
boolean
supportsUnionAll
()
throws
SQLException
{
return
false
;
}
/**
* 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 jere, 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
;
// For now...
}
/**
* 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
8190
;
}
/**
* 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
getMaxColumnsInTable
();
}
/**
* 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?
* Theoretically, all of them!
*
* @return the max columns
* @exception SQLException if a database access error occurs
*/
public
int
getMaxColumnsInOrderBy
()
throws
SQLException
{
return
getMaxColumnsInTable
();
}
/**
* What is the maximum number of columns in a "SELECT" list?
* Theoretically, all of them!
*
* @return the max columns
* @exception SQLException if a database access error occurs
*/
public
int
getMaxColumnsInSelect
()
throws
SQLException
{
return
getMaxColumnsInTable
();
}
/**
* What is the maximum number of columns in a table? From the
* create_table(l) manual page...
*
* "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
;
}
/**
* What is the maximum length of an index (in bytes)? Now, does
* the spec. mean name of an index (in which case its 32, the
* same as a table) or does it mean length of an index element
* (in which case its 8192, the size of a row) or does it mean
* the number of rows it can access (in which case it 2^32 -
* a 4 byte OID number)? I think its the length of an index
* element, personally, so Im setting it to 8192.
*
* @return max index length in bytes
* @exception SQLException if a database access error occurs
*/
public
int
getMaxIndexLength
()
throws
SQLException
{
return
8192
;
}
public
int
getMaxSchemaNameLength
()
throws
SQLException
{
// XXX-Not Implemented
}
/**
* 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
}
/**
* What is the maximum length of a single row? (not including
* blobs). 8192 is defined in PostgreSQL.
*
* @return max row size in bytes
* @exception SQLException if a database access error occurs
*/
public
int
getMaxRowSize
()
throws
SQLException
{
return
8192
;
}
/**
* 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
{
return
8192
;
}
/**
* 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? Theoretically, this is the same number as the
* number of tables allowable. In practice tho, it is much smaller
* since the number of tables is limited by the statement, we
* return 1024 here - this is just a number I came up with (being
* the number of tables roughly of three characters each that you
* can fit inside a 8192 character buffer with comma separators).
*
* @return the maximum
* @exception SQLException if a database access error occurs
*/
public
int
getMaxTablesInSelect
()
throws
SQLException
{
return
1024
;
}
/**
* 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_SERIALIZABLE
;
}
/**
* 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
*
* @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
)
return
true
;
else
return
false
;
}
/**
* Are both data definition and data manipulation transactions
* supported? I checked it, and could not do a CREATE TABLE
* within a transaction, so I am assuming that we don't
*
* @return true if so
* @exception SQLException if a database access error occurs
*/
public
boolean
supportsDataDefinitionAndDataManipulationTransactions
()
throws
SQLException
{
return
false
;
}
/**
* 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
true
;
}
/**
* Does a data definition statement within a transaction force
* the transaction to commit? I think this means something like:
*
* 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;
*
* 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
false
;
}
/**
* Get a description of stored procedures available in a catalog
*
* Only procedure descriptions matching the schema and procedure
* name criteria are returned. They are ordered by PROCEDURE_SCHEM
* and PROCEDURE_NAME
*
* Each procedure description has the following columns:
* PROCEDURE_CAT String => procedure catalog (may be null)
* PROCEDURE_SCHEM String => procedure schema (may be null)
* PROCEDURE_NAME String => procedure name
* Field 4 reserved (make it null)
* Field 5 reserved (make it null)
* Field 6 reserved (make it null)
* REMARKS String => explanatory comment on the procedure
* PROCEDURE_TYPE short => kind of procedure
* * procedureResultUnknown - May return a result
* * procedureNoResult - Does not return a result
* * procedureReturnsResult - Returns a result
*
* @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
{
Field
[]
f
=
new
Field
[
8
];
// the field descriptors for the new ResultSet
static
final
int
iVarcharOid
=
1043
;
// This is the OID for a varchar()
static
final
int
iInt2Oid
=
21
;
// This is the OID for an int2
ResultSet
r
;
// ResultSet for the SQL query that we need to do
Vector
v
;
// The new ResultSet tuple stuff
String
remarks
=
new
String
(
"no remarks"
);
Field
[
0
]
=
new
Field
(
conn
,
new
String
(
"PROCEDURE_CAT"
),
iVarcharOid
,
32
);
Field
[
1
]
=
new
Field
(
conn
,
new
String
(
"PROCEDURE_SCHEM"
),
iVarcharOid
,
32
);
Field
[
2
]
=
new
Field
(
conn
,
new
String
(
"PROCEDURE_NAME"
),
iVarcharOid
,
32
);
Field
[
3
]
=
null
;
Field
[
4
]
=
null
;
Field
[
5
]
=
null
;
Field
[
6
]
=
new
Field
(
conn
,
new
String
(
"REMARKS"
),
iVarcharOid
,
8192
);
Field
[
7
]
=
new
Field
(
conn
,
new
String
(
"PROCEDURE_TYPE"
),
iInt2Oid
,
2
);
r
=
conn
.
ExecSQL
(
"select proname, proretset from pg_proc order by proname"
);
if
(
r
.
getColumnCount
()
!=
2
||
r
.
getTupleCount
()
<=
1
)
throw
new
SQLException
(
"Unexpected return from query for procedure list"
);
while
(
r
.
next
())
{
byte
[][]
tuple
=
new
byte
[
8
][
0
];
String
name
=
r
.
getString
(
1
);
String
remarks
=
new
String
(
"no remarks"
);
boolean
retset
=
r
.
getBoolean
(
2
);
byte
[
0
]
=
null
;
// Catalog name
byte
[
1
]
=
null
;
// Schema name
byte
[
2
]
=
name
.
getBytes
();
// Procedure name
byte
[
3
]
=
null
;
// Reserved
byte
[
4
]
=
null
;
// Reserved
byte
[
5
]
=
null
;
// Reserved
byte
[
6
]
=
remarks
.
getBytes
();
// Remarks
if
(
retset
)
byte
[
7
]
=
procedureReturnsResult
;
else
byte
[
7
]
=
procedureNoResult
;
v
.
addElement
(
byte
);
}
return
new
ResultSet
(
conn
,
f
,
v
,
"OK"
,
1
);
}
public
java
.
sql
.
ResultSet
getProcedureColumns
(
String
catalog
,
String
schemaPattern
,
String
procedureNamePattern
,
String
columnNamePattern
)
throws
SQLException
{
// XXX-Not Implemented
}
public
java
.
sql
.
ResultSet
getTables
(
String
catalog
,
String
schemaPattern
,
String
tableNamePattern
,
String
types
[])
throws
SQLException
{
// XXX-Not Implemented
}
public
java
.
sql
.
ResultSet
getSchemas
()
throws
SQLException
{
// XXX-Not Implemented
}
public
java
.
sql
.
ResultSet
getCatalogs
()
throws
SQLException
{
// XXX-Not Implemented
}
public
java
.
sql
.
ResultSet
getTableTypes
()
throws
SQLException
{
// XXX-Not Implemented
}
public
java
.
sql
.
ResultSet
getColumns
(
String
catalog
,
String
schemaPattern
,
String
tableNamePattern
,
String
columnNamePattern
)
throws
SQLException
{
// XXX-Not Implemented
}
public
java
.
sql
.
ResultSet
getColumnPrivileges
(
String
catalog
,
String
schema
,
String
table
,
String
columnNamePattern
)
throws
SQLException
{
// XXX-Not Implemented
}
public
java
.
sql
.
ResultSet
getTablePrivileges
(
String
catalog
,
String
schemaPattern
,
String
tableNamePattern
)
throws
SQLException
{
// XXX-Not Implemented
}
public
java
.
sql
.
ResultSet
getBestRowIdentifier
(
String
catalog
,
String
schema
,
String
table
,
int
scope
,
boolean
nullable
)
throws
SQLException
{
// XXX-Not Implemented
}
public
java
.
sql
.
ResultSet
getVersionColumns
(
String
catalog
,
String
schema
,
String
table
)
throws
SQLException
{
// XXX-Not Implemented
}
public
java
.
sql
.
ResultSet
getPrimaryKeys
(
String
catalog
,
String
schema
,
String
table
)
throws
SQLException
{
// XXX-Not Implemented
}
public
java
.
sql
.
ResultSet
getImportedKeys
(
String
catalog
,
String
schema
,
String
table
)
throws
SQLException
{
// XXX-Not Implemented
}
public
java
.
sql
.
ResultSet
getExportedKeys
(
String
catalog
,
String
schema
,
String
table
)
throws
SQLException
{
// XXX-Not Implemented
}
public
java
.
sql
.
ResultSet
getCrossReference
(
String
primaryCatalog
,
String
primarySchema
,
String
primaryTable
,
String
foreignCatalog
,
String
foreignSchema
,
String
foreignTable
)
throws
SQLException
{
// XXX-Not Implemented
}
public
java
.
sql
.
ResultSet
getTypeInfo
()
throws
SQLException
{
// XXX-Not Implemented
}
public
java
.
sql
.
ResultSet
getIndexInfo
(
String
catalog
,
String
schema
,
String
table
,
boolean
unique
,
boolean
approximate
)
throws
SQLException
{
// XXX-Not Implemented
}
}
src/interfaces/jdbc/postgresql/Driver.java
0 → 100644
View file @
ff246d7b
package
postgresql
;
import
java.sql.*
;
import
java.util.*
;
import
postgresql.*
;
/**
* @version 1.0 15-APR-1997
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
*
* The Java SQL framework allows for multiple database drivers. Each
* driver should supply a class that implements the Driver interface
*
* The DriverManager will try to load as many drivers as it can find and then
* for any given connection request, it will ask each driver in turn to try
* to connect to the target URL.
*
* It is strongly recommended that each Driver class should be small and
* standalone so that the Driver class can be loaded and queried without
* bringing in vast quantities of supporting code.
*
* When a Driver class is loaded, it should create an instance of itself and
* register it with the DriverManager. This means that a user can load and
* register a driver by doing Class.forName("foo.bah.Driver")
*
* @see postgresql.Connection
* @see java.sql.Driver
*/
public
class
Driver
implements
java
.
sql
.
Driver
{
static
{
try
{
new
Driver
();
}
catch
(
SQLException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Construct a new driver and register it with DriverManager
*
* @exception SQLException for who knows what!
*/
public
Driver
()
throws
SQLException
{
java
.
sql
.
DriverManager
.
registerDriver
(
this
);
}
/**
* Try to make a database connection to the given URL. The driver
* should return "null" if it realizes it is the wrong kind of
* driver to connect to the given URL. This will be common, as
* when the JDBC driverManager is asked to connect to a given URL,
* it passes the URL to each loaded driver in turn.
*
* The driver should raise an SQLException if it is the right driver
* to connect to the given URL, but has trouble connecting to the
* database.
*
* The java.util.Properties argument can be used to pass arbitrary
* string tag/value pairs as connection arguments. Normally, at least
* "user" and "password" properties should be included in the
* properties.
*
* Our protocol takes the form:
* <PRE>
* jdbc:postgresql://host:port/database
* </PRE>
*
* @param url the URL of the database to connect to
* @param info a list of arbitrary tag/value pairs as connection
* arguments
* @return a connection to the URL or null if it isnt us
* @exception SQLException if a database access error occurs
* @see java.sql.Driver#connect
*/
public
java
.
sql
.
Connection
connect
(
String
url
,
Properties
info
)
throws
SQLException
{
DriverURL
dr
=
new
DriverURL
(
url
);
int
port
;
if
(!(
dr
.
protocol
().
equals
(
"jdbc"
)))
return
null
;
if
(!(
dr
.
subprotocol
().
equals
(
"postgresql"
)))
return
null
;
if
(
dr
.
host
().
equals
(
"unknown"
))
return
null
;
port
=
dr
.
port
();
if
(
port
==
-
1
)
port
=
5432
;
// Default PostgreSQL port
return
new
Connection
(
dr
.
host
(),
port
,
info
,
dr
.
database
(),
url
,
this
);
}
/**
* Returns true if the driver thinks it can open a connection to the
* given URL. Typically, drivers will return true if they understand
* the subprotocol specified in the URL and false if they don't. Our
* protocols start with jdbc:postgresql:
*
* @see java.sql.Driver#acceptsURL
* @param url the URL of the driver
* @return true if this driver accepts the given URL
* @exception SQLException if a database-access error occurs
* (Dont know why it would *shrug*)
*/
public
boolean
acceptsURL
(
String
url
)
throws
SQLException
{
DriverURL
dr
=
new
DriverURL
(
url
);
if
(
dr
.
protocol
().
equals
(
"jdbc"
))
if
(
dr
.
subprotocol
().
equals
(
"postgresql"
))
return
true
;
return
false
;
}
/**
* The getPropertyInfo method is intended to allow a generic GUI
* tool to discover what properties it should prompt a human for
* in order to get enough information to connect to a database.
* Note that depending on the values the human has supplied so
* far, additional values may become necessary, so it may be necessary
* to iterate through several calls to getPropertyInfo
*
* @param url the Url of the database to connect to
* @param info a proposed list of tag/value pairs that will be sent on
* connect open.
* @return An array of DriverPropertyInfo objects describing
* possible properties. This array may be an empty array if
* no properties are required
* @exception SQLException if a database-access error occurs
* @see java.sql.Driver#getPropertyInfo
*/
public
DriverPropertyInfo
[]
getPropertyInfo
(
String
url
,
Properties
info
)
throws
SQLException
{
return
null
;
// We don't need anything except
// the username, which is a default
}
/**
* Gets the drivers major version number
*
* @return the drivers major version number
*/
public
int
getMajorVersion
()
{
return
1
;
}
/**
* Get the drivers minor version number
*
* @return the drivers minor version number
*/
public
int
getMinorVersion
()
{
return
0
;
}
/**
* Report whether the driver is a genuine JDBC compliant driver. A
* driver may only report "true" here if it passes the JDBC compliance
* tests, otherwise it is required to return false. JDBC compliance
* requires full support for the JDBC API and full support for SQL 92
* Entry Level.
*/
public
boolean
jdbcCompliant
()
{
return
false
;
}
}
/**
* The DriverURL class splits a JDBC URL into its subcomponents
*
* protocol:subprotocol:/[/host[:port]/][database]
*/
class
DriverURL
{
private
String
protocol
,
subprotocol
,
host
,
database
;
private
int
port
=
-
1
;
/**
* Constructs a new DriverURL, splitting the specified URL into its
* component parts
*/
public
DriverURL
(
String
url
)
throws
SQLException
{
int
a
,
b
,
c
;
String
tmp
,
hostport
,
dbportion
;
a
=
url
.
indexOf
(
':'
);
if
(
a
==
-
1
)
throw
new
SQLException
(
"Bad URL Protocol specifier"
);
b
=
url
.
indexOf
(
':'
,
a
+
1
);
if
(
b
==
-
1
)
throw
new
SQLException
(
"Bad URL Subprotocol specifier"
);
protocol
=
new
String
(
url
.
substring
(
0
,
a
));
subprotocol
=
new
String
(
url
.
substring
(
a
+
1
,
b
));
tmp
=
new
String
(
url
.
substring
(
b
+
1
,
url
.
length
()));
if
(
tmp
.
length
()
<
2
)
throw
new
SQLException
(
"Bad URL Database specifier"
);
if
(!
tmp
.
substring
(
0
,
2
).
equals
(
"//"
))
{
host
=
new
String
(
"unknown"
);
port
=
-
1
;
database
=
new
String
(
tmp
.
substring
(
1
,
tmp
.
length
()));
return
;
}
dbportion
=
new
String
(
tmp
.
substring
(
2
,
tmp
.
length
()));
c
=
dbportion
.
indexOf
(
'/'
);
if
(
c
==
-
1
)
throw
new
SQLException
(
"Bad URL Database specifier"
);
a
=
dbportion
.
indexOf
(
':'
);
if
(
a
==
-
1
)
{
host
=
new
String
(
dbportion
.
substring
(
0
,
c
));
port
=
-
1
;
database
=
new
String
(
dbportion
.
substring
(
c
+
1
,
dbportion
.
length
()));
}
else
{
host
=
new
String
(
dbportion
.
substring
(
0
,
a
));
port
=
Integer
.
valueOf
(
dbportion
.
substring
(
a
+
1
,
c
)).
intValue
();
database
=
new
String
(
dbportion
.
substring
(
c
+
1
,
dbportion
.
length
()));
}
}
/**
* Returns the protocol name of the DriverURL
*/
public
String
protocol
()
{
return
protocol
;
}
/**
* Returns the subprotocol name of the DriverURL
*/
public
String
subprotocol
()
{
return
subprotocol
;
}
/**
* Returns the hostname portion of the URL
*/
public
String
host
()
{
return
host
;
}
/**
* Returns the port number portion of the URL
* or -1 if no port was specified
*/
public
int
port
()
{
return
port
;
}
/**
* Returns the database name of the URL
*/
public
String
database
()
{
return
database
;
}
}
src/interfaces/jdbc/postgresql/Field.java
0 → 100644
View file @
ff246d7b
package
postgresql
;
import
java.lang.*
;
import
java.sql.*
;
import
java.util.*
;
import
postgresql.*
;
/**
* postgresql.Field is a class used to describe fields in a PostgreSQL ResultSet
*
* @version 1.0 15-APR-1997
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
*/
public
class
Field
{
int
length
;
// Internal Length of this field
int
oid
;
// OID of the type
Connection
conn
;
// Connection Instantation
String
name
;
// Name of this field
int
sql_type
=
-
1
;
// The entry in java.sql.Types for this field
String
type_name
=
null
;
// The sql type name
/**
* 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
)
{
this
.
conn
=
conn
;
this
.
name
=
name
;
this
.
oid
=
oid
;
this
.
length
=
length
;
}
/**
* the ResultSet and ResultMetaData both need to handle the SQL
* type, which is gained from another query. Note that we cannot
* use getObject() in this, since getObject uses getSQLType().
*
* @return the entry in Types that refers to this field
* @exception SQLException if a database access error occurs
*/
public
int
getSQLType
()
throws
SQLException
{
if
(
sql_type
==
-
1
)
{
ResultSet
result
=
(
postgresql
.
ResultSet
)
conn
.
ExecSQL
(
"select typname from pg_type where oid = "
+
oid
);
if
(
result
.
getColumnCount
()
!=
1
||
result
.
getTupleCount
()
!=
1
)
throw
new
SQLException
(
"Unexpected return from query for type"
);
result
.
next
();
type_name
=
result
.
getString
(
1
);
if
(
type_name
.
equals
(
"int2"
))
sql_type
=
Types
.
SMALLINT
;
else
if
(
type_name
.
equals
(
"int4"
))
sql_type
=
Types
.
INTEGER
;
else
if
(
type_name
.
equals
(
"int8"
))
sql_type
=
Types
.
BIGINT
;
else
if
(
type_name
.
equals
(
"cash"
))
sql_type
=
Types
.
DECIMAL
;
else
if
(
type_name
.
equals
(
"money"
))
sql_type
=
Types
.
DECIMAL
;
else
if
(
type_name
.
equals
(
"float4"
))
sql_type
=
Types
.
REAL
;
else
if
(
type_name
.
equals
(
"float8"
))
sql_type
=
Types
.
DOUBLE
;
else
if
(
type_name
.
equals
(
"bpchar"
))
sql_type
=
Types
.
CHAR
;
else
if
(
type_name
.
equals
(
"varchar"
))
sql_type
=
Types
.
VARCHAR
;
else
if
(
type_name
.
equals
(
"bool"
))
sql_type
=
Types
.
BIT
;
else
if
(
type_name
.
equals
(
"date"
))
sql_type
=
Types
.
DATE
;
else
if
(
type_name
.
equals
(
"time"
))
sql_type
=
Types
.
TIME
;
else
if
(
type_name
.
equals
(
"abstime"
))
sql_type
=
Types
.
TIMESTAMP
;
else
sql_type
=
Types
.
OTHER
;
}
return
sql_type
;
}
/**
* We also need to get the type name as returned by the back end.
* This is held in type_name AFTER a call to getSQLType. Since
* we get this information within getSQLType (if it isn't already
* done), we can just call getSQLType and throw away the result.
*
* @return the String representation of the type of this field
* @exception SQLException if a database access error occurs
*/
public
String
getTypeName
()
throws
SQLException
{
int
sql
=
getSQLType
();
return
type_name
;
}
}
src/interfaces/jdbc/postgresql/PG_Object.java
0 → 100644
View file @
ff246d7b
package
postgresql
;
import
java.lang.*
;
import
java.sql.*
;
import
java.util.*
;
import
postgresql.*
;
/**
* postgresql.PG_Object is a class used to describe unknown types
* An unknown type is any type that is unknown by JDBC Standards
*
* @version 1.0 15-APR-1997
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
*/
public
class
PG_Object
{
public
String
type
;
public
String
value
;
/**
* Constructor for the PostgreSQL generic object
*
* @param type a string describing the type of the object
* @param value a string representation of the value of the object
*/
public
PG_Object
(
String
type
,
String
value
)
{
this
.
type
=
type
;
this
.
value
=
value
;
}
}
src/interfaces/jdbc/postgresql/PreparedStatement.java
0 → 100644
View file @
ff246d7b
package
postgresql
;
import
java.io.*
;
import
java.math.*
;
import
java.sql.*
;
import
java.text.*
;
import
java.util.*
;
/**
* @version 1.0 15-APR-1997
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
*
* A SQL Statement is pre-compiled and stored in a PreparedStatement object.
* This object can then be used to efficiently execute this statement multiple
* times.
*
* <B>Note:</B> The setXXX methods for setting IN parameter values must
* specify types that are compatible with the defined SQL type of the input
* parameter. For instance, if the IN parameter has SQL type Integer, then
* setInt should be used.
*
* 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
{
String
sql
;
String
[]
templateStrings
;
String
[]
inStrings
;
Connection
connection
;
/**
* Constructor for the PreparedStatement class. Split the SQL statement
* into segments - separated by the arguments. When we rebuild the
* thing with the arguments, we can substitute the args and join the
* whole thing together.
*
* @param conn the instanatiating connection
* @param sql the SQL statement with ? for IN markers
* @exception SQLException if something bad occurs
*/
public
PreparedStatement
(
Connection
connection
,
String
sql
)
throws
SQLException
{
super
(
connection
);
Vector
v
=
new
Vector
();
boolean
inQuotes
=
false
;
int
lastParmEnd
=
0
,
i
;
this
.
sql
=
sql
;
this
.
connection
=
connection
;
for
(
i
=
0
;
i
<
sql
.
length
();
++
i
)
{
int
c
=
sql
.
charAt
(
i
);
if
(
c
==
'\''
)
inQuotes
=
!
inQuotes
;
if
(
c
==
'?'
&&
!
inQuotes
)
{
v
.
addElement
(
sql
.
substring
(
lastParmEnd
,
i
));
lastParmEnd
=
i
+
1
;
}
}
v
.
addElement
(
sql
.
substring
(
lastParmEnd
,
sql
.
length
()));
templateStrings
=
new
String
[
v
.
size
()];
inStrings
=
new
String
[
v
.
size
()
-
1
];
clearParameters
();
for
(
i
=
0
;
i
<
templateStrings
.
length
;
++
i
)
templateStrings
[
i
]
=
(
String
)
v
.
elementAt
(
i
);
}
/**
* A Prepared SQL query is executed and its ResultSet is returned
*
* @return a ResultSet that contains the data produced by the
* query - never null
* @exception SQLException if a database access error occurs
*/
public
java
.
sql
.
ResultSet
executeQuery
()
throws
SQLException
{
StringBuffer
s
=
new
StringBuffer
();
int
i
;
for
(
i
=
0
;
i
<
inStrings
.
length
;
++
i
)
{
if
(
inStrings
[
i
]
==
null
)
throw
new
SQLException
(
"No value specified for parameter "
+
(
i
+
1
));
s
.
append
(
templateStrings
[
i
]);
s
.
append
(
inStrings
[
i
]);
}
s
.
append
(
templateStrings
[
inStrings
.
length
]);
return
super
.
executeQuery
(
s
.
toString
());
// in Statement class
}
/**
* Execute a SQL INSERT, UPDATE or DELETE statement. In addition,
* SQL statements that return nothing such as SQL DDL statements can
* be executed.
*
* @return either the row count for INSERT, UPDATE or DELETE; or
* 0 for SQL statements that return nothing.
* @exception SQLException if a database access error occurs
*/
public
int
executeUpdate
()
throws
SQLException
{
StringBuffer
s
=
new
StringBuffer
();
int
i
;
for
(
i
=
0
;
i
<
inStrings
.
length
;
++
i
)
{
if
(
inStrings
[
i
]
==
null
)
throw
new
SQLException
(
"No value specified for parameter "
+
(
i
+
1
));
s
.
append
(
templateStrings
[
i
]);
s
.
append
(
inStrings
[
i
]);
}
s
.
append
(
templateStrings
[
inStrings
.
length
]);
return
super
.
executeUpdate
(
s
.
toString
());
// in Statement class
}
/**
* Set a parameter to SQL NULL
*
* <B>Note:</B> You must specify the parameters SQL type (although
* PostgreSQL ignores it)
*
* @param parameterIndex the first parameter is 1, etc...
* @param sqlType the SQL type code defined in java.sql.Types
* @exception SQLException if a database access error occurs
*/
public
void
setNull
(
int
parameterIndex
,
int
sqlType
)
throws
SQLException
{
set
(
parameterIndex
,
"null"
);
}
/**
* Set a parameter to a Java boolean value. The driver converts this
* to a SQL BIT value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public
void
setBoolean
(
int
parameterIndex
,
boolean
x
)
throws
SQLException
{
set
(
parameterIndex
,
x
?
"'t'"
:
"'f'"
);
}
/**
* Set a parameter to a Java byte value. The driver converts this to
* a SQL TINYINT value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public
void
setByte
(
int
parameterIndex
,
byte
x
)
throws
SQLException
{
set
(
parameterIndex
,
(
new
Integer
(
x
)).
toString
());
}
/**
* Set a parameter to a Java short value. The driver converts this
* to a SQL SMALLINT value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public
void
setShort
(
int
parameterIndex
,
short
x
)
throws
SQLException
{
set
(
parameterIndex
,
(
new
Integer
(
x
)).
toString
());
}
/**
* Set a parameter to a Java int value. The driver converts this to
* a SQL INTEGER value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public
void
setInt
(
int
parameterIndex
,
int
x
)
throws
SQLException
{
set
(
parameterIndex
,
(
new
Integer
(
x
)).
toString
());
}
/**
* Set a parameter to a Java long value. The driver converts this to
* a SQL BIGINT value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public
void
setLong
(
int
parameterIndex
,
long
x
)
throws
SQLException
{
set
(
parameterIndex
,
(
new
Long
(
x
)).
toString
());
}
/**
* Set a parameter to a Java float value. The driver converts this
* to a SQL FLOAT value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public
void
setFloat
(
int
parameterIndex
,
float
x
)
throws
SQLException
{
set
(
parameterIndex
,
(
new
Float
(
x
)).
toString
());
}
/**
* 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...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public
void
setDouble
(
int
parameterIndex
,
double
x
)
throws
SQLException
{
set
(
parameterIndex
,
(
new
Double
(
x
)).
toString
());
}
/**
* Set a parameter to a java.lang.BigDecimal value. The driver
* converts this to a SQL NUMERIC value when it sends it to the
* database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public
void
setBigDecimal
(
int
parameterIndex
,
BigDecimal
x
)
throws
SQLException
{
set
(
parameterIndex
,
x
.
toString
());
}
/**
* 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.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public
void
setString
(
int
parameterIndex
,
String
x
)
throws
SQLException
{
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.
*
* @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
{
throw
new
SQLException
(
"Binary Data not supported"
);
}
/**
* Set a parameter to a java.sql.Date value. The driver converts this
* to a SQL DATE value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public
void
setDate
(
int
parameterIndex
,
java
.
sql
.
Date
x
)
throws
SQLException
{
DateFormat
df
=
DateFormat
.
getDateInstance
();
set
(
parameterIndex
,
"'"
+
df
.
format
(
x
)
+
"'"
);
}
/**
* 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.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public
void
setTime
(
int
parameterIndex
,
Time
x
)
throws
SQLException
{
set
(
parameterIndex
,
"'"
+
x
.
toString
()
+
"'"
);
}
/**
* Set a parameter to a java.sql.Timestamp value. The driver converts
* this to a SQL TIMESTAMP value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public
void
setTimestamp
(
int
parameterIndex
,
Timestamp
x
)
throws
SQLException
{
set
(
parameterIndex
,
"'"
+
x
.
toString
()
+
"'"
);
}
/**
* When a very large ASCII value is input to a LONGVARCHAR 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. The JDBC driver will do any necessary conversion from
* ASCII to the database char format.
*
* <B>Note:</B> This stream object can either be a standard Java
* stream object or your own subclass that implements the standard
* interface.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @param length the number of bytes in the stream
* @exception SQLException if a database access error occurs
*/
public
void
setAsciiStream
(
int
parameterIndex
,
InputStream
x
,
int
length
)
throws
SQLException
{
setBinaryStream
(
parameterIndex
,
x
,
length
);
}
/**
* When a very large Unicode value is input to a LONGVARCHAR 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. The JDBC driver will do any necessary conversion from
* UNICODE to the database char format.
*
* <B>Note:</B> This stream object can either be a standard Java
* stream object or your own subclass that implements the standard
* interface.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public
void
setUnicodeStream
(
int
parameterIndex
,
InputStream
x
,
int
length
)
throws
SQLException
{
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.
*
* <B>Note:</B> This stream object can either be a standard Java
* stream object or your own subclass that implements the standard
* interface.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public
void
setBinaryStream
(
int
parameterIndex
,
InputStream
x
,
int
length
)
throws
SQLException
{
throw
new
SQLException
(
"InputStream as parameter not supported"
);
}
/**
* 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
* release the resources used by the current parameter values; this
* can be done by calling clearParameters
*
* @exception SQLException if a database access error occurs
*/
public
void
clearParameters
()
throws
SQLException
{
int
i
;
for
(
i
=
0
;
i
<
inStrings
.
length
;
i
++)
inStrings
[
i
]
=
null
;
}
/**
* Set the value of a parameter using an object; use the java.lang
* equivalent objects for integral values.
*
* The given Java object will be converted to the targetSqlType before
* being sent to the database.
*
* note that this method may be used to pass database-specific
* abstract data types. This is done by using a Driver-specific
* Java type and using a targetSqlType of java.sql.Types.OTHER
*
* @param parameterIndex the first parameter is 1...
* @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.
* @exception SQLException if a database access error occurs
*/
public
void
setObject
(
int
parameterIndex
,
Object
x
,
int
targetSqlType
,
int
scale
)
throws
SQLException
{
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
());
case
Types
.
DATE
:
setDate
(
parameterIndex
,
(
java
.
sql
.
Date
)
x
);
case
Types
.
TIME
:
setTime
(
parameterIndex
,
(
Time
)
x
);
case
Types
.
TIMESTAMP
:
setTimestamp
(
parameterIndex
,
(
Timestamp
)
x
);
case
Types
.
OTHER
:
setString
(
parameterIndex
,
((
PG_Object
)
x
).
value
);
default
:
throw
new
SQLException
(
"Unknown Types value"
);
}
}
public
void
setObject
(
int
parameterIndex
,
Object
x
,
int
targetSqlType
)
throws
SQLException
{
setObject
(
parameterIndex
,
x
,
targetSqlType
,
0
);
}
public
void
setObject
(
int
parameterIndex
,
Object
x
)
throws
SQLException
{
if
(
x
instanceof
String
)
setString
(
parameterIndex
,
(
String
)
x
);
else
if
(
x
instanceof
BigDecimal
)
setBigDecimal
(
parameterIndex
,
(
BigDecimal
)
x
);
else
if
(
x
instanceof
Integer
)
setInt
(
parameterIndex
,
((
Integer
)
x
).
intValue
());
else
if
(
x
instanceof
Long
)
setLong
(
parameterIndex
,
((
Long
)
x
).
longValue
());
else
if
(
x
instanceof
Float
)
setFloat
(
parameterIndex
,
((
Float
)
x
).
floatValue
());
else
if
(
x
instanceof
Double
)
setDouble
(
parameterIndex
,
((
Double
)
x
).
doubleValue
());
else
if
(
x
instanceof
byte
[])
setBytes
(
parameterIndex
,
(
byte
[])
x
);
else
if
(
x
instanceof
java
.
sql
.
Date
)
setDate
(
parameterIndex
,
(
java
.
sql
.
Date
)
x
);
else
if
(
x
instanceof
Time
)
setTime
(
parameterIndex
,
(
Time
)
x
);
else
if
(
x
instanceof
Timestamp
)
setTimestamp
(
parameterIndex
,
(
Timestamp
)
x
);
else
if
(
x
instanceof
Boolean
)
setBoolean
(
parameterIndex
,
((
Boolean
)
x
).
booleanValue
());
else
if
(
x
instanceof
PG_Object
)
setString
(
parameterIndex
,
((
PG_Object
)
x
).
value
);
else
throw
new
SQLException
(
"Unknown object type"
);
}
/**
* Some prepared statements return multiple results; the execute method
* 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
* @exception SQLException if a database access error occurs
*/
public
boolean
execute
()
throws
SQLException
{
StringBuffer
s
=
new
StringBuffer
();
int
i
;
for
(
i
=
0
;
i
<
inStrings
.
length
;
++
i
)
{
if
(
inStrings
[
i
]
==
null
)
throw
new
SQLException
(
"No value specified for parameter "
+
(
i
+
1
));
s
.
append
(
templateStrings
[
i
]);
s
.
append
(
inStrings
[
i
]);
}
s
.
append
(
templateStrings
[
inStrings
.
length
]);
return
super
.
execute
(
s
.
toString
());
// in Statement class
}
// **************************************************************
// 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
* set for us.
*
* @param paramIndex the index into the inString
* @param s a string to be stored
* @exception SQLException if something goes wrong
*/
private
void
set
(
int
paramIndex
,
String
s
)
throws
SQLException
{
if
(
paramIndex
<
1
||
paramIndex
>
inStrings
.
length
)
throw
new
SQLException
(
"Parameter index out of range"
);
inStrings
[
paramIndex
-
1
]
=
s
;
}
}
src/interfaces/jdbc/postgresql/ResultSet.java
0 → 100644
View file @
ff246d7b
package
postgresql
;
import
java.lang.*
;
import
java.io.*
;
import
java.math.*
;
import
java.text.*
;
import
java.util.*
;
import
java.sql.*
;
import
postgresql.*
;
/**
* @version 1.0 15-APR-1997
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
*
* A ResultSet provides access to a table of data generated by executing a
* Statement. The table rows are retrieved in sequence. Within a row its
* column values can be accessed in any order.
*
* 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.
*
* 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
* efficient. Columns are numbered from 1.
*
* For maximum portability, ResultSet columns within each row should be read
* in left-to-right order and each column should be read only once.
*
* For the getXXX methods, the JDBC driver attempts to convert the underlying
* data to the specified Java type and returns a suitable Java value. See the
* JDBC specification for allowable mappings from SQL types to Java types with
* the ResultSet getXXX methods.
*
* 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
* 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
* the programmer to guarentee that they actually refer to the intended
* columns.
*
* 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.
*
* The number, types and properties of a ResultSet's columns are provided by
* the ResultSetMetaData object returned by the getMetaData method.
*
* @see ResultSetMetaData
* @see java.sql.ResultSet
*/
public
class
ResultSet
implements
java
.
sql
.
ResultSet
{
Vector
rows
;
// The results
Field
fields
[];
// The field descriptions
String
status
;
// Status of the result
int
updateCount
;
// How many rows did we get back?
int
current_row
;
// Our pointer to where we are at
byte
[][]
this_row
;
// the current row result
Connection
connection
;
// the connection which we returned from
SQLWarning
warnings
=
null
;
// The warning chain
boolean
wasNullFlag
=
false
;
// the flag for wasNull()
// We can chain multiple resultSets together - this points to
// next resultSet in the chain.
private
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
)
{
this
.
connection
=
conn
;
this
.
fields
=
fields
;
this
.
rows
=
tuples
;
this
.
status
=
status
;
this
.
updateCount
=
updateCount
;
this
.
this_row
=
null
;
this
.
current_row
=
-
1
;
}
/**
* 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.
*
* 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.
*
* <B>Note:</B> A ResultSet is automatically closed by the Statement
* 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. A ResultSet is also automatically closed
* when it is garbage collected.
*
* @exception SQLException if a database access error occurs
*/
public
void
close
()
throws
SQLException
{
// No-op
}
/**
* A column may have the value of SQL NULL; wasNull() reports whether
* the last column read had this special value. Note that you must
* first call getXXX on a column to try to read its value and then
* call wasNull() to find if the value was SQL NULL
*
* @return true if the last column read was SQL NULL
* @exception SQLException if a database access error occurred
*/
public
boolean
wasNull
()
throws
SQLException
{
return
wasNullFlag
;
}
/**
* Get the value of a column in the current row as a Java String
*
* @param columnIndex the first column is 1, the second is 2...
* @return the column value, null for SQL NULL
* @exception SQLException if a database access error occurs
*/
public
String
getString
(
int
columnIndex
)
throws
SQLException
{
byte
[]
bytes
=
getBytes
(
columnIndex
);
if
(
bytes
==
null
)
return
null
;
return
new
String
(
bytes
);
}
/**
* Get the value of a column in the current row as a Java boolean
*
* @param columnIndex the first column is 1, the second is 2...
* @return the column value, false for SQL NULL
* @exception SQLException if a database access error occurs
*/
public
boolean
getBoolean
(
int
columnIndex
)
throws
SQLException
{
String
s
=
getString
(
columnIndex
);
if
(
s
!=
null
)
{
int
c
=
s
.
charAt
(
0
);
return
((
c
==
't'
)
||
(
c
==
'T'
));
}
return
false
;
// SQL NULL
}
/**
* Get the value of a column in the current row as a Java byte.
*
* @param columnIndex the first column is 1, the second is 2,...
* @return the column value; 0 if SQL NULL
* @exception SQLException if a database access error occurs
*/
public
byte
getByte
(
int
columnIndex
)
throws
SQLException
{
String
s
=
getString
(
columnIndex
);
if
(
s
!=
null
)
{
try
{
return
Byte
.
parseByte
(
s
);
}
catch
(
NumberFormatException
e
)
{
throw
new
SQLException
(
"Bad Byte Form: "
+
s
);
}
}
return
0
;
// SQL NULL
}
/**
* Get the value of a column in the current row as a Java short.
*
* @param columnIndex the first column is 1, the second is 2,...
* @return the column value; 0 if SQL NULL
* @exception SQLException if a database access error occurs
*/
public
short
getShort
(
int
columnIndex
)
throws
SQLException
{
String
s
=
getString
(
columnIndex
);
if
(
s
!=
null
)
{
try
{
return
Short
.
parseShort
(
s
);
}
catch
(
NumberFormatException
e
)
{
throw
new
SQLException
(
"Bad Short Form: "
+
s
);
}
}
return
0
;
// SQL NULL
}
/**
* Get the value of a column in the current row as a Java int.
*
* @param columnIndex the first column is 1, the second is 2,...
* @return the column value; 0 if SQL NULL
* @exception SQLException if a database access error occurs
*/
public
int
getInt
(
int
columnIndex
)
throws
SQLException
{
String
s
=
getString
(
columnIndex
);
if
(
s
!=
null
)
{
try
{
return
Integer
.
parseInt
(
s
);
}
catch
(
NumberFormatException
e
)
{
throw
new
SQLException
(
"Bad Integer Form: "
+
s
);
}
}
return
0
;
// SQL NULL
}
/**
* Get the value of a column in the current row as a Java long.
*
* @param columnIndex the first column is 1, the second is 2,...
* @return the column value; 0 if SQL NULL
* @exception SQLException if a database access error occurs
*/
public
long
getLong
(
int
columnIndex
)
throws
SQLException
{
String
s
=
getString
(
columnIndex
);
if
(
s
!=
null
)
{
try
{
return
Long
.
parseLong
(
s
);
}
catch
(
NumberFormatException
e
)
{
throw
new
SQLException
(
"Bad Long Form: "
+
s
);
}
}
return
0
;
// SQL NULL
}
/**
* Get the value of a column in the current row as a Java float.
*
* @param columnIndex the first column is 1, the second is 2,...
* @return the column value; 0 if SQL NULL
* @exception SQLException if a database access error occurs
*/
public
float
getFloat
(
int
columnIndex
)
throws
SQLException
{
String
s
=
getString
(
columnIndex
);
if
(
s
!=
null
)
{
try
{
return
Float
.
valueOf
(
s
).
floatValue
();
}
catch
(
NumberFormatException
e
)
{
throw
new
SQLException
(
"Bad Float Form: "
+
s
);
}
}
return
0
;
// SQL NULL
}
/**
* Get the value of a column in the current row as a Java double.
*
* @param columnIndex the first column is 1, the second is 2,...
* @return the column value; 0 if SQL NULL
* @exception SQLException if a database access error occurs
*/
public
double
getDouble
(
int
columnIndex
)
throws
SQLException
{
String
s
=
getString
(
columnIndex
);
if
(
s
!=
null
)
{
try
{
return
Double
.
valueOf
(
s
).
doubleValue
();
}
catch
(
NumberFormatException
e
)
{
throw
new
SQLException
(
"Bad Double Form: "
+
s
);
}
}
return
0
;
// SQL NULL
}
/**
* Get the value of a column in the current row as a
* java.lang.BigDecimal object
*
* @param columnIndex the first column is 1, the second is 2...
* @param scale the number of digits to the right of the decimal
* @return the column value; if the value is SQL NULL, null
* @exception SQLException if a database access error occurs
*/
public
BigDecimal
getBigDecimal
(
int
columnIndex
,
int
scale
)
throws
SQLException
{
String
s
=
getString
(
columnIndex
);
BigDecimal
val
;
if
(
s
!=
null
)
{
try
{
val
=
new
BigDecimal
(
s
);
}
catch
(
NumberFormatException
e
)
{
throw
new
SQLException
(
"Bad BigDecimal Form: "
+
s
);
}
try
{
return
val
.
setScale
(
scale
);
}
catch
(
ArithmeticException
e
)
{
throw
new
SQLException
(
"Bad BigDecimal Form: "
+
s
);
}
}
return
null
;
// SQL NULL
}
/**
* Get the value of a column in the current row as a Java byte array
* The bytes represent the raw values returned by the driver.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @return the column value; if the value is SQL NULL, the result
* is null
* @exception SQLException if a database access error occurs
*/
public
byte
[]
getBytes
(
int
columnIndex
)
throws
SQLException
{
if
(
columnIndex
<
1
||
columnIndex
>
fields
.
length
)
throw
new
SQLException
(
"Column Index out of range"
);
wasNullFlag
=
(
this_row
[
columnIndex
-
1
]
==
null
);
return
this_row
[
columnIndex
-
1
];
}
/**
* Get the value of a column in the current row as a java.sql.Date
* object
*
* @param columnIndex the first column is 1, the second is 2...
* @return the column value; null if SQL NULL
* @exception SQLException if a database access error occurs
*/
public
java
.
sql
.
Date
getDate
(
int
columnIndex
)
throws
SQLException
{
String
s
=
getString
(
columnIndex
);
if
(
s
!=
null
)
{
try
{
if
(
s
.
length
()
!=
10
)
throw
new
NumberFormatException
(
"Wrong Length!"
);
int
mon
=
Integer
.
parseInt
(
s
.
substring
(
0
,
2
));
int
day
=
Integer
.
parseInt
(
s
.
substring
(
3
,
5
));
int
yr
=
Integer
.
parseInt
(
s
.
substring
(
6
));
return
new
java
.
sql
.
Date
(
yr
-
1900
,
mon
-
1
,
day
);
}
catch
(
NumberFormatException
e
)
{
throw
new
SQLException
(
"Bad Date Form: "
+
s
);
}
}
return
null
;
// SQL NULL
}
/**
* Get the value of a column in the current row as a java.sql.Time
* object
*
* @param columnIndex the first column is 1, the second is 2...
* @return the column value; null if SQL NULL
* @exception SQLException if a database access error occurs
*/
public
Time
getTime
(
int
columnIndex
)
throws
SQLException
{
String
s
=
getString
(
columnIndex
);
if
(
s
!=
null
)
{
try
{
if
(
s
.
length
()
!=
5
&&
s
.
length
()
!=
8
)
throw
new
NumberFormatException
(
"Wrong Length!"
);
int
hr
=
Integer
.
parseInt
(
s
.
substring
(
0
,
2
));
int
min
=
Integer
.
parseInt
(
s
.
substring
(
3
,
5
));
int
sec
=
(
s
.
length
()
==
5
)
?
0
:
Integer
.
parseInt
(
s
.
substring
(
6
));
return
new
Time
(
hr
,
min
,
sec
);
}
catch
(
NumberFormatException
e
)
{
throw
new
SQLException
(
"Bad Time Form: "
+
s
);
}
}
return
null
;
// SQL NULL
}
/**
* Get the value of a column in the current row as a
* java.sql.Timestamp object
*
* @param columnIndex the first column is 1, the second is 2...
* @return the column value; null if SQL NULL
* @exception SQLException if a database access error occurs
*/
public
Timestamp
getTimestamp
(
int
columnIndex
)
throws
SQLException
{
String
s
=
getString
(
columnIndex
);
DateFormat
df
=
DateFormat
.
getDateInstance
();
if
(
s
!=
null
)
{
try
{
java
.
sql
.
Date
d
=
(
java
.
sql
.
Date
)
df
.
parse
(
s
);
return
new
Timestamp
(
d
.
getTime
());
}
catch
(
ParseException
e
)
{
throw
new
SQLException
(
"Bad Timestamp Format: "
+
s
);
}
}
return
null
;
// SQL NULL
}
/**
* A column value can be retrieved as a stream of ASCII characters
* and then read in chunks from the stream. This method is
* particular suitable for retrieving large LONGVARCHAR values.
* The JDBC driver will do any necessary conversion from the
* database format into ASCII.
*
* <B>Note:</B> All the data in the returned stream must be read
* prior to getting the value of any other column. The next call
* to a get method implicitly closes the stream. Also, a stream
* may return 0 for available() whether there is data available
* or not.
*
* We implement an ASCII stream as a Binary stream - we should really
* do the data conversion, but I cannot be bothered to implement this
* right now.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @return a Java InputStream that delivers the database column
* value as a stream of one byte ASCII characters. If the
* value is SQL NULL then the result is null
* @exception SQLException if a database access error occurs
* @see getBinaryStream
*/
public
InputStream
getAsciiStream
(
int
columnIndex
)
throws
SQLException
{
return
getBinaryStream
(
columnIndex
);
}
/**
* A column value can also be retrieved as a stream of Unicode
* characters. We implement this as a binary stream.
*
* @param columnIndex the first column is 1, the second is 2...
* @return a Java InputStream that delivers the database column value
* as a stream of two byte Unicode characters. If the value is
* SQL NULL, then the result is null
* @exception SQLException if a database access error occurs
* @see getAsciiStream
* @see getBinaryStream
*/
public
InputStream
getUnicodeStream
(
int
columnIndex
)
throws
SQLException
{
return
getBinaryStream
(
columnIndex
);
}
/**
* A column value can also be retrieved as a binary strea. This
* method is suitable for retrieving LONGVARBINARY values.
*
* @param columnIndex the first column is 1, the second is 2...
* @return a Java InputStream that delivers the database column value
* as a stream of two byte Unicode characters. If the value is
* SQL NULL, then the result is null
* @exception SQLException if a database access error occurs
* @see getAsciiStream
* @see getUnicodeStream
*/
public
InputStream
getBinaryStream
(
int
columnIndex
)
throws
SQLException
{
byte
b
[]
=
getBytes
(
columnIndex
);
if
(
b
!=
null
)
return
new
ByteArrayInputStream
(
b
);
return
null
;
// SQL NULL
}
/**
* The following routines simply convert the columnName into
* a columnIndex and then call the appropriate routine above.
*
* @param columnName is the SQL name of the column
* @return the column value
* @exception SQLException if a database access error occurs
*/
public
String
getString
(
String
columnName
)
throws
SQLException
{
return
getString
(
findColumn
(
columnName
));
}
public
boolean
getBoolean
(
String
columnName
)
throws
SQLException
{
return
getBoolean
(
findColumn
(
columnName
));
}
public
byte
getByte
(
String
columnName
)
throws
SQLException
{
return
getByte
(
findColumn
(
columnName
));
}
public
short
getShort
(
String
columnName
)
throws
SQLException
{
return
getShort
(
findColumn
(
columnName
));
}
public
int
getInt
(
String
columnName
)
throws
SQLException
{
return
getInt
(
findColumn
(
columnName
));
}
public
long
getLong
(
String
columnName
)
throws
SQLException
{
return
getLong
(
findColumn
(
columnName
));
}
public
float
getFloat
(
String
columnName
)
throws
SQLException
{
return
getFloat
(
findColumn
(
columnName
));
}
public
double
getDouble
(
String
columnName
)
throws
SQLException
{
return
getDouble
(
findColumn
(
columnName
));
}
public
BigDecimal
getBigDecimal
(
String
columnName
,
int
scale
)
throws
SQLException
{
return
getBigDecimal
(
findColumn
(
columnName
),
scale
);
}
public
byte
[]
getBytes
(
String
columnName
)
throws
SQLException
{
return
getBytes
(
findColumn
(
columnName
));
}
public
java
.
sql
.
Date
getDate
(
String
columnName
)
throws
SQLException
{
return
getDate
(
findColumn
(
columnName
));
}
public
Time
getTime
(
String
columnName
)
throws
SQLException
{
return
getTime
(
findColumn
(
columnName
));
}
public
Timestamp
getTimestamp
(
String
columnName
)
throws
SQLException
{
return
getTimestamp
(
findColumn
(
columnName
));
}
public
InputStream
getAsciiStream
(
String
columnName
)
throws
SQLException
{
return
getAsciiStream
(
findColumn
(
columnName
));
}
public
InputStream
getUnicodeStream
(
String
columnName
)
throws
SQLException
{
return
getUnicodeStream
(
findColumn
(
columnName
));
}
public
InputStream
getBinaryStream
(
String
columnName
)
throws
SQLException
{
return
getBinaryStream
(
findColumn
(
columnName
));
}
/**
* The first warning reported by calls on this ResultSet is
* returned. Subsequent ResultSet warnings will be chained
* to this SQLWarning.
*
* The warning chain is automatically cleared each time a new
* row is read.
*
* <B>Note:</B> This warning chain only covers warnings caused by
* ResultSet methods. Any warnings caused by statement methods
* (such as reading OUT parameters) will be chained on the
* Statement object.
*
* @return the first SQLWarning or null;
* @exception SQLException if a database access error occurs.
*/
public
SQLWarning
getWarnings
()
throws
SQLException
{
return
warnings
;
}
/**
* After this call, getWarnings returns null until a new warning
* is reported for this ResultSet
*
* @exception SQLException if a database access error occurs
*/
public
void
clearWarnings
()
throws
SQLException
{
warnings
=
null
;
}
/**
* Get the name of the SQL cursor used by this ResultSet
*
* In SQL, a result table is retrieved though 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.
*
* JDBC supports this SQL feature by providing the name of the
* SQL cursor used by a ResultSet. The current row of a ResulSet
* is also the current row of this SQL cursor.
*
* <B>Note:</B> If positioned update is not supported, a SQLException
* is thrown.
*
* @return the ResultSet's SQL cursor name.
* @exception SQLException if a database access error occurs
*/
public
String
getCursorName
()
throws
SQLException
{
return
connection
.
getCursorName
();
}
/**
* The numbers, types and properties of a ResultSet's columns are
* provided by the getMetaData method
*
* @return a description of the ResultSet's columns
* @exception SQLException if a database access error occurs
*/
public
java
.
sql
.
ResultSetMetaData
getMetaData
()
throws
SQLException
{
return
new
ResultSetMetaData
(
rows
,
fields
);
}
/**
* Get the value of a column in the current row as a Java object
*
* This method will return the value of the given column as a
* Java object. The type of the Java object will be the default
* Java Object type corresponding to the column's SQL type, following
* the mapping specified in the JDBC specification.
*
* This method may also be used to read database specific abstract
* data types.
*
* @param columnIndex the first column is 1, the second is 2...
* @return a Object holding the column value
* @exception SQLException if a database access error occurs
*/
public
Object
getObject
(
int
columnIndex
)
throws
SQLException
{
Field
field
;
if
(
columnIndex
<
1
||
columnIndex
>
fields
.
length
)
throw
new
SQLException
(
"Column index out of range"
);
field
=
fields
[
columnIndex
-
1
];
switch
(
field
.
getSQLType
())
{
case
Types
.
BIT
:
return
new
Boolean
(
getBoolean
(
columnIndex
));
case
Types
.
SMALLINT
:
return
new
Integer
(
getInt
(
columnIndex
));
case
Types
.
INTEGER
:
return
new
Integer
(
getInt
(
columnIndex
));
case
Types
.
BIGINT
:
return
new
Long
(
getLong
(
columnIndex
));
case
Types
.
NUMERIC
:
return
getBigDecimal
(
columnIndex
,
0
);
case
Types
.
REAL
:
return
new
Float
(
getFloat
(
columnIndex
));
case
Types
.
DOUBLE
:
return
new
Double
(
getDouble
(
columnIndex
));
case
Types
.
CHAR
:
case
Types
.
VARCHAR
:
return
getString
(
columnIndex
);
case
Types
.
DATE
:
return
getDate
(
columnIndex
);
case
Types
.
TIME
:
return
getTime
(
columnIndex
);
case
Types
.
TIMESTAMP
:
return
getTimestamp
(
columnIndex
);
default
:
return
new
PG_Object
(
field
.
getTypeName
(),
getString
(
columnIndex
));
}
}
/**
* Get the value of a column in the current row as a Java object
*
* This method will return the value of the given column as a
* Java object. The type of the Java object will be the default
* Java Object type corresponding to the column's SQL type, following
* the mapping specified in the JDBC specification.
*
* This method may also be used to read database specific abstract
* data types.
*
* @param columnName is the SQL name of the column
* @return a Object holding the column value
* @exception SQLException if a database access error occurs
*/
public
Object
getObject
(
String
columnName
)
throws
SQLException
{
return
getObject
(
findColumn
(
columnName
));
}
/**
* Map a ResultSet column name to a ResultSet column index
*
* @param columnName the name of the column
* @return the column index
* @exception SQLException if a database access error occurs
*/
public
int
findColumn
(
String
columnName
)
throws
SQLException
{
int
i
;
for
(
i
=
0
;
i
<
fields
.
length
;
++
i
)
if
(
fields
[
i
].
name
.
equalsIgnoreCase
(
columnName
))
return
(
i
+
1
);
throw
new
SQLException
(
"Column name not found"
);
}
// ************************************************************
// END OF PUBLIC INTERFACE
// ************************************************************
/**
* 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
ResultSet
getNext
()
{
return
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
*
* getTupleCount returns the number of rows
*
* @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
;
}
}
src/interfaces/jdbc/postgresql/ResultSetMetaData.java
0 → 100644
View file @
ff246d7b
package
postgresql
;
import
java.lang.*
;
import
java.sql.*
;
import
java.util.*
;
import
postgresql.*
;
/**
* @version 1.0 15-APR-1997
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
*
* A ResultSetMetaData object can be used to find out about the types and
* properties of the columns in a ResultSet
*
* @see java.sql.ResultSetMetaData
*/
public
class
ResultSetMetaData
implements
java
.
sql
.
ResultSetMetaData
{
Vector
rows
;
Field
[]
fields
;
/**
* Initialise for a result with a tuple set and
* a field descriptor set
*
* @param rows the Vector of rows returned by the ResultSet
* @param fields the array of field descriptors
*/
public
ResultSetMetaData
(
Vector
rows
,
Field
[]
fields
)
{
this
.
rows
=
rows
;
this
.
fields
=
fields
;
}
/**
* Whats the number of columns in the ResultSet?
*
* @return the number
* @exception SQLException if a database access error occurs
*/
public
int
getColumnCount
()
throws
SQLException
{
return
fields
.
length
;
}
/**
* Is the column automatically numbered (and thus read-only)
* I believe that PostgreSQL does not support this feature.
*
* @param column the first column is 1, the second is 2...
* @return true if so
* @exception SQLException if a database access error occurs
*/
public
boolean
isAutoIncrement
(
int
column
)
throws
SQLException
{
return
false
;
}
/**
* Does a column's case matter? ASSUMPTION: Any field that is
* not obviously case insensitive is assumed to be case sensitive
*
* @param column the first column is 1, the second is 2...
* @return true if so
* @exception SQLException if a database access error occurs
*/
public
boolean
isCaseSensitive
(
int
column
)
throws
SQLException
{
int
sql_type
=
getField
(
column
).
getSQLType
();
switch
(
sql_type
)
{
case
Types
.
SMALLINT
:
case
Types
.
INTEGER
:
case
Types
.
FLOAT
:
case
Types
.
REAL
:
case
Types
.
DOUBLE
:
case
Types
.
DATE
:
case
Types
.
TIME
:
case
Types
.
TIMESTAMP
:
return
false
;
default
:
return
true
;
}
}
/**
* Can the column be used in a WHERE clause? Basically for
* this, I split the functions into two types: recognised
* types (which are always useable), and OTHER types (which
* may or may not be useable). The OTHER types, for now, I
* will assume they are useable. We should really query the
* catalog to see if they are useable.
*
* @param column the first column is 1, the second is 2...
* @return true if they can be used in a WHERE clause
* @exception SQLException if a database access error occurs
*/
public
boolean
isSearchable
(
int
column
)
throws
SQLException
{
int
sql_type
=
getField
(
column
).
getSQLType
();
// This switch is pointless, I know - but it is a set-up
// for further expansion.
switch
(
sql_type
)
{
case
Types
.
OTHER
:
return
true
;
default
:
return
true
;
}
}
/**
* Is the column a cash value? 6.1 introduced the cash/money
* type, which haven't been incorporated as of 970414, so I
* just check the type name for both 'cash' and 'money'
*
* @param column the first column is 1, the second is 2...
* @return true if its a cash column
* @exception SQLException if a database access error occurs
*/
public
boolean
isCurrency
(
int
column
)
throws
SQLException
{
String
type_name
=
getField
(
column
).
getTypeName
();
if
(
type_name
.
equals
(
"cash"
))
return
true
;
if
(
type_name
.
equals
(
"money"
))
return
true
;
return
false
;
}
/**
* Can you put a NULL in this column? I think this is always
* true in 6.1's case. It would only be false if the field had
* been defined NOT NULL (system catalogs could be queried?)
*
* @param column the first column is 1, the second is 2...
* @return one of the columnNullable values
* @exception SQLException if a database access error occurs
*/
public
int
isNullable
(
int
column
)
throws
SQLException
{
return
columnNullable
;
// We can always put NULL in
}
/**
* Is the column a signed number? In PostgreSQL, all numbers
* are signed, so this is trivial. However, strings are not
* signed (duh!)
*
* @param column the first column is 1, the second is 2...
* @return true if so
* @exception SQLException if a database access error occurs
*/
public
boolean
isSigned
(
int
column
)
throws
SQLException
{
int
sql_type
=
getField
(
column
).
getSQLType
();
switch
(
sql_type
)
{
case
Types
.
SMALLINT
:
case
Types
.
INTEGER
:
case
Types
.
FLOAT
:
case
Types
.
REAL
:
case
Types
.
DOUBLE
:
return
true
;
case
Types
.
DATE
:
case
Types
.
TIME
:
case
Types
.
TIMESTAMP
:
return
false
;
// I don't know about these?
default
:
return
false
;
}
}
/**
* What is the column's normal maximum width in characters?
*
* @param column the first column is 1, the second is 2, etc.
* @return the maximum width
* @exception SQLException if a database access error occurs
*/
public
int
getColumnDisplaySize
(
int
column
)
throws
SQLException
{
int
max
=
getColumnLabel
(
column
).
length
();
int
i
;
for
(
i
=
0
;
i
<
rows
.
size
();
++
i
)
{
byte
[][]
x
=
(
byte
[][])(
rows
.
elementAt
(
i
));
int
xl
=
x
[
column
-
1
].
length
;
if
(
xl
>
max
)
max
=
xl
;
}
return
max
;
}
/**
* What is the suggested column title for use in printouts and
* displays? We suggest the ColumnName!
*
* @param column the first column is 1, the second is 2, etc.
* @return the column label
* @exception SQLException if a database access error occurs
*/
public
String
getColumnLabel
(
int
column
)
throws
SQLException
{
return
getColumnName
(
column
);
}
/**
* What's a column's name?
*
* @param column the first column is 1, the second is 2, etc.
* @return the column name
* @exception SQLException if a databvase access error occurs
*/
public
String
getColumnName
(
int
column
)
throws
SQLException
{
return
getField
(
column
).
name
;
}
/**
* What is a column's table's schema? This relies on us knowing
* the table name....which I don't know how to do as yet. The
* JDBC specification allows us to return "" if this is not
* applicable.
*
* @param column the first column is 1, the second is 2...
* @return the Schema
* @exception SQLException if a database access error occurs
*/
public
String
getSchemaName
(
int
column
)
throws
SQLException
{
String
table_name
=
getTableName
(
column
);
// If the table name is invalid, so are we.
if
(
table_name
.
equals
(
""
))
return
""
;
return
""
;
// Ok, so I don't know how to
// do this as yet.
}
/**
* What is a column's number of decimal digits.
*
* @param column the first column is 1, the second is 2...
* @return the precision
* @exception SQLException if a database access error occurs
*/
public
int
getPrecision
(
int
column
)
throws
SQLException
{
int
sql_type
=
getField
(
column
).
getSQLType
();
switch
(
sql_type
)
{
case
Types
.
SMALLINT
:
return
5
;
case
Types
.
INTEGER
:
return
10
;
case
Types
.
REAL
:
return
8
;
case
Types
.
FLOAT
:
return
16
;
case
Types
.
DOUBLE
:
return
16
;
default
:
throw
new
SQLException
(
"no precision for non-numeric data types."
);
}
}
/**
* What is a column's number of digits to the right of the
* decimal point?
*
* @param column the first column is 1, the second is 2...
* @return the scale
* @exception SQLException if a database access error occurs
*/
public
int
getScale
(
int
column
)
throws
SQLException
{
int
sql_type
=
getField
(
column
).
getSQLType
();
switch
(
sql_type
)
{
case
Types
.
SMALLINT
:
return
0
;
case
Types
.
INTEGER
:
return
0
;
case
Types
.
REAL
:
return
8
;
case
Types
.
FLOAT
:
return
16
;
case
Types
.
DOUBLE
:
return
16
;
default
:
throw
new
SQLException
(
"no scale for non-numeric data types"
);
}
}
/**
* Whats a column's table's name? How do I find this out? Both
* getSchemaName() and getCatalogName() rely on knowing the table
* Name, so we need this before we can work on them.
*
* @param column the first column is 1, the second is 2...
* @return column name, or "" if not applicable
* @exception SQLException if a database access error occurs
*/
public
String
getTableName
(
int
column
)
throws
SQLException
{
return
""
;
}
/**
* What's a column's table's catalog name? As with getSchemaName(),
* we can say that if getTableName() returns n/a, then we can too -
* otherwise, we need to work on it.
*
* @param column the first column is 1, the second is 2...
* @return catalog name, or "" if not applicable
* @exception SQLException if a database access error occurs
*/
public
String
getCatalogName
(
int
column
)
throws
SQLException
{
String
table_name
=
getTableName
(
column
);
if
(
table_name
.
equals
(
""
))
return
""
;
return
""
;
// As with getSchemaName(), this
// is just the start of it.
}
/**
* What is a column's SQL Type? (java.sql.Type int)
*
* @param column the first column is 1, the second is 2, etc.
* @return the java.sql.Type value
* @exception SQLException if a database access error occurs
* @see postgresql.Field#getSQLType
* @see java.sql.Types
*/
public
int
getColumnType
(
int
column
)
throws
SQLException
{
return
getField
(
column
).
getSQLType
();
}
/**
* Whats is the column's data source specific type name?
*
* @param column the first column is 1, the second is 2, etc.
* @return the type name
* @exception SQLException if a database access error occurs
*/
public
String
getColumnTypeName
(
int
column
)
throws
SQLException
{
return
getField
(
column
).
getTypeName
();
}
/**
* Is the column definitely not writable? In reality, we would
* have to check the GRANT/REVOKE stuff for this to be effective,
* and I haven't really looked into that yet, so this will get
* re-visited.
*
* @param column the first column is 1, the second is 2, etc.
* @return true if so
* @exception SQLException if a database access error occurs
*/
public
boolean
isReadOnly
(
int
column
)
throws
SQLException
{
return
false
;
}
/**
* Is it possible for a write on the column to succeed? Again, we
* would in reality have to check the GRANT/REVOKE stuff, which
* I haven't worked with as yet. However, if it isn't ReadOnly, then
* it is obviously writable.
*
* @param column the first column is 1, the second is 2, etc.
* @return true if so
* @exception SQLException if a database access error occurs
*/
public
boolean
isWritable
(
int
column
)
throws
SQLException
{
if
(
isReadOnly
(
column
))
return
true
;
else
return
false
;
}
/**
* Will a write on this column definately succeed? Hmmm...this
* is a bad one, since the two preceding functions have not been
* really defined. I cannot tell is the short answer. I thus
* return isWritable() just to give us an idea.
*
* @param column the first column is 1, the second is 2, etc..
* @return true if so
* @exception SQLException if a database access error occurs
*/
public
boolean
isDefinitelyWritable
(
int
column
)
throws
SQLException
{
return
isWritable
(
column
);
}
// ********************************************************
// END OF PUBLIC INTERFACE
// ********************************************************
/**
* For several routines in this package, we need to convert
* a columnIndex into a Field[] descriptor. Rather than do
* the same code several times, here it is.
*
* @param columnIndex the first column is 1, the second is 2...
* @return the Field description
* @exception SQLException if a database access error occurs
*/
private
Field
getField
(
int
columnIndex
)
throws
SQLException
{
if
(
columnIndex
<
1
||
columnIndex
>
fields
.
length
)
throw
new
SQLException
(
"Column index out of range"
);
return
fields
[
columnIndex
-
1
];
}
}
src/interfaces/jdbc/postgresql/Statement.java
0 → 100644
View file @
ff246d7b
package
postgresql
;
import
java.sql.*
;
/**
* @version 1.0 15-APR-1997
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
*
* A Statement object is used for executing a static SQL statement and
* obtaining the results produced by it.
*
* Only one ResultSet per Statement can be open at any point in time.
* Therefore, if the reading of one ResultSet is interleaved with the
* reading of another, each must have been generated by different
* Statements. All statement execute methods implicitly close a
* statement's current ResultSet if an open one exists.
*
* @see java.sql.Statement
* @see ResultSet
*/
public
class
Statement
implements
java
.
sql
.
Statement
{
Connection
connection
;
// The connection who created us
ResultSet
result
=
null
;
// The current results
SQLWarning
warnings
=
null
;
// The warnings chain.
int
maxrows
=
0
;
// maximum no. of rows; 0 = unlimited
int
timeout
=
0
;
// The timeout for a query (not used)
boolean
escapeProcessing
=
true
;
// escape processing flag
/**
* Constructor for a Statement. It simply sets the connection
* that created us.
*
* @param c the Connection instantation that creates us
*/
public
Statement
(
Connection
c
)
{
connection
=
c
;
}
/**
* Execute a SQL statement that retruns a single ResultSet
*
* @param sql typically a static SQL SELECT statement
* @return a ResulSet that contains the data produced by the query
* @exception SQLException if a database access error occurs
*/
public
java
.
sql
.
ResultSet
executeQuery
(
String
sql
)
throws
SQLException
{
this
.
execute
(
sql
);
while
(
result
!=
null
&&
!
result
.
reallyResultSet
())
result
=
result
.
getNext
();
if
(
result
==
null
)
throw
new
SQLException
(
"no results returned"
);
return
result
;
}
/**
* Execute a SQL INSERT, UPDATE or DELETE statement. In addition
* SQL statements that return nothing such as SQL DDL statements
* can be executed
*
* @param sql a SQL statement
* @return either a row count, or 0 for SQL commands
* @exception SQLException if a database access error occurs
*/
public
int
executeUpdate
(
String
sql
)
throws
SQLException
{
this
.
execute
(
sql
);
if
(
result
.
reallyResultSet
())
throw
new
SQLException
(
"results returned"
);
return
this
.
getUpdateCount
();
}
/**
* 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.
*
* <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
{
result
=
null
;
}
/**
* 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
SQLException
(
"Attempt to setMaxFieldSize failed - compile time default"
);
}
/**
* 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
;
}
/**
* Cancel can be used by one thread to cancel a statement that
* is being executed by another thread. However, PostgreSQL is
* a sync. sort of thing, so this really has no meaning - we
* define it as a no-op (i.e. you can't cancel, but there is no
* error if you try.)
*
* @exception SQLException only because thats the spec.
*/
public
void
cancel
()
throws
SQLException
{
// No-op
}
/**
* 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.
*
* The Warning chain is automatically cleared each time a statement
* is (re)executed.
*
* <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
;
}
/**
* After this call, getWarnings returns null until a new warning
* is reported for this Statement.
*
* @exception SQLException if a database access error occurs (why?)
*/
public
void
clearWarnings
()
throws
SQLException
{
warnings
=
null
;
}
/**
* setCursorName defines the SQL cursor name that will be used by
* subsequent execute methods. This name can then be used in SQL
* positioned update/delete statements to identify the current row
* in the ResultSet generated by this statement. If a database
* doesn't support positioned update/delete, this method is a
* no-op.
*
* <B>Note:</B> By definition, positioned update/delete execution
* must be done by a different Statement than the one which
* generated the ResultSet being used for positioning. Also, cursor
* names must be unique within a Connection.
*
* We throw an additional constriction. There can only be one
* cursor active at any one time.
*
* @param name the new cursor name
* @exception SQLException if a database access error occurs
*/
public
void
setCursorName
(
String
name
)
throws
SQLException
{
connection
.
setCursorName
(
name
);
}
/**
* Execute a SQL statement that may return multiple results. We
* don't have to worry about this since we do not support multiple
* ResultSets. You can use getResultSet or getUpdateCount to
* retrieve the result.
*
* @param sql any SQL statement
* @return true if the next result is a ResulSet, false if it is
* an update count or there are no more results
* @exception SQLException if a database access error occurs
*/
public
boolean
execute
(
String
sql
)
throws
SQLException
{
result
=
connection
.
ExecSQL
(
sql
);
return
(
result
!=
null
&&
result
.
reallyResultSet
());
}
/**
* 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
{
return
result
;
}
/**
* getUpdateCount returns the current result as an update count,
* if the result is a ResultSet or there are no more results, -1
* is returned. It should only be called once per result.
*
* @return the current result as an update count.
* @exception SQLException if a database access error occurs
*/
public
int
getUpdateCount
()
throws
SQLException
{
if
(
result
==
null
)
return
-
1
;
if
(
result
.
reallyResultSet
())
return
-
1
;
return
result
.
getResultCount
();
}
/**
* getMoreResults moves to a Statement's next result. If it returns
* true, this result is a ResulSet.
*
* @return true if the next ResultSet is valid
* @exception SQLException if a database access error occurs
*/
public
boolean
getMoreResults
()
throws
SQLException
{
result
=
result
.
getNext
();
return
(
result
!=
null
&&
result
.
reallyResultSet
());
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment