Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit25dadc8

Browse files
author
Peter Mount
committed
Another attempt at 7.0
1 parentaafff4a commit25dadc8

38 files changed

+17359
-0
lines changed
Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
packageorg.postgresql.fastpath;
2+
3+
importjava.io.*;
4+
importjava.lang.*;
5+
importjava.net.*;
6+
importjava.util.*;
7+
importjava.sql.*;
8+
importorg.postgresql.util.*;
9+
10+
// Important: There are a lot of debug code commented out. Please do not
11+
// delete these.
12+
13+
/**
14+
* This class implements the Fastpath api.
15+
*
16+
* <p>This is a means of executing functions imbeded in the org.postgresql backend
17+
* from within a java application.
18+
*
19+
* <p>It is based around the file src/interfaces/libpq/fe-exec.c
20+
*
21+
*
22+
* <p><b>Implementation notes:</b>
23+
*
24+
* <p><b><em>Network protocol:</em></b>
25+
*
26+
* <p>The code within the backend reads integers in reverse.
27+
*
28+
* <p>There is work in progress to convert all of the protocol to
29+
* network order but it may not be there for v6.3
30+
*
31+
* <p>When fastpath switches, simply replace SendIntegerReverse() with
32+
* SendInteger()
33+
*
34+
* @see org.postgresql.FastpathFastpathArg
35+
* @see org.postgresql.LargeObject
36+
*/
37+
publicclassFastpath
38+
{
39+
// This maps the functions names to their id's (possible unique just
40+
// to a connection).
41+
protectedHashtablefunc =newHashtable();
42+
43+
protectedorg.postgresql.Connectionconn;// our connection
44+
protectedorg.postgresql.PG_Streamstream;// the network stream
45+
46+
/**
47+
* Initialises the fastpath system
48+
*
49+
* <p><b>Important Notice</b>
50+
* <br>This is called from org.postgresql.Connection, and should not be called
51+
* from client code.
52+
*
53+
* @param conn org.postgresql.Connection to attach to
54+
* @param stream The network stream to the backend
55+
*/
56+
publicFastpath(org.postgresql.Connectionconn,org.postgresql.PG_Streamstream)
57+
{
58+
this.conn=conn;
59+
this.stream=stream;
60+
//DriverManager.println("Fastpath initialised");
61+
}
62+
63+
/**
64+
* Send a function call to the PostgreSQL backend
65+
*
66+
* @param fnid Function id
67+
* @param resulttype True if the result is an integer, false for other results
68+
* @param args FastpathArguments to pass to fastpath
69+
* @return null if no data, Integer if an integer result, or byte[] otherwise
70+
* @exception SQLException if a database-access error occurs.
71+
*/
72+
publicObjectfastpath(intfnid,booleanresulttype,FastpathArg[]args)throwsSQLException
73+
{
74+
// added Oct 7 1998 to give us thread safety
75+
synchronized(stream) {
76+
77+
// send the function call
78+
try {
79+
// 70 is 'F' in ASCII. Note: don't use SendChar() here as it adds padding
80+
// that confuses the backend. The 0 terminates the command line.
81+
stream.SendInteger(70,1);
82+
stream.SendInteger(0,1);
83+
84+
//stream.SendIntegerReverse(fnid,4);
85+
//stream.SendIntegerReverse(args.length,4);
86+
stream.SendInteger(fnid,4);
87+
stream.SendInteger(args.length,4);
88+
89+
for(inti=0;i<args.length;i++)
90+
args[i].send(stream);
91+
92+
// This is needed, otherwise data can be lost
93+
stream.flush();
94+
95+
}catch(IOExceptionioe) {
96+
thrownewPSQLException("postgresql.fp.send",newInteger(fnid),ioe);
97+
}
98+
99+
// Now handle the result
100+
101+
// We should get 'V' on sucess or 'E' on error. Anything else is treated
102+
// as an error.
103+
//int in = stream.ReceiveChar();
104+
//DriverManager.println("ReceiveChar() = "+in+" '"+((char)in)+"'");
105+
//if(in!='V') {
106+
//if(in=='E')
107+
//throw new SQLException(stream.ReceiveString(4096));
108+
//throw new SQLException("Fastpath: expected 'V' from backend, got "+((char)in));
109+
//}
110+
111+
// Now loop, reading the results
112+
Objectresult =null;// our result
113+
while(true) {
114+
intin =stream.ReceiveChar();
115+
//DriverManager.println("ReceiveChar() = "+in+" '"+((char)in)+"'");
116+
switch(in)
117+
{
118+
case'V':
119+
break;
120+
121+
//------------------------------
122+
// Function returned properly
123+
//
124+
case'G':
125+
intsz =stream.ReceiveIntegerR(4);
126+
//DriverManager.println("G: size="+sz); //debug
127+
128+
// Return an Integer if
129+
if(resulttype)
130+
result =newInteger(stream.ReceiveIntegerR(sz));
131+
else {
132+
bytebuf[] =newbyte[sz];
133+
stream.Receive(buf,0,sz);
134+
result =buf;
135+
}
136+
break;
137+
138+
//------------------------------
139+
// Error message returned
140+
case'E':
141+
thrownewPSQLException("postgresql.fp.error",stream.ReceiveString(4096));
142+
143+
//------------------------------
144+
// Notice from backend
145+
case'N':
146+
conn.addWarning(stream.ReceiveString(4096));
147+
break;
148+
149+
//------------------------------
150+
// End of results
151+
//
152+
// Here we simply return res, which would contain the result
153+
// processed earlier. If no result, this already contains null
154+
case'0':
155+
//DriverManager.println("returning "+result);
156+
returnresult;
157+
158+
case'Z':
159+
break;
160+
161+
default:
162+
thrownewPSQLException("postgresql.fp.protocol",newCharacter((char)in));
163+
}
164+
}
165+
}
166+
}
167+
168+
/**
169+
* Send a function call to the PostgreSQL backend by name.
170+
*
171+
* Note: the mapping for the procedure name to function id needs to exist,
172+
* usually to an earlier call to addfunction().
173+
*
174+
* This is the prefered method to call, as function id's can/may change
175+
* between versions of the backend.
176+
*
177+
* For an example of how this works, refer to org.postgresql.LargeObject
178+
*
179+
* @param name Function name
180+
* @param resulttype True if the result is an integer, false for other
181+
* results
182+
* @param args FastpathArguments to pass to fastpath
183+
* @return null if no data, Integer if an integer result, or byte[] otherwise
184+
* @exception SQLException if name is unknown or if a database-access error
185+
* occurs.
186+
* @see org.postgresql.LargeObject
187+
*/
188+
publicObjectfastpath(Stringname,booleanresulttype,FastpathArg[]args)throwsSQLException
189+
{
190+
//DriverManager.println("Fastpath: calling "+name);
191+
returnfastpath(getID(name),resulttype,args);
192+
}
193+
194+
/**
195+
* This convenience method assumes that the return value is an Integer
196+
* @param name Function name
197+
* @param args Function arguments
198+
* @return integer result
199+
* @exception SQLException if a database-access error occurs or no result
200+
*/
201+
publicintgetInteger(Stringname,FastpathArg[]args)throwsSQLException
202+
{
203+
Integeri = (Integer)fastpath(name,true,args);
204+
if(i==null)
205+
thrownewPSQLException("postgresql.fp.expint",name);
206+
returni.intValue();
207+
}
208+
209+
/**
210+
* This convenience method assumes that the return value is an Integer
211+
* @param name Function name
212+
* @param args Function arguments
213+
* @return byte[] array containing result
214+
* @exception SQLException if a database-access error occurs or no result
215+
*/
216+
publicbyte[]getData(Stringname,FastpathArg[]args)throwsSQLException
217+
{
218+
return (byte[])fastpath(name,false,args);
219+
}
220+
221+
/**
222+
* This adds a function to our lookup table.
223+
*
224+
* <p>User code should use the addFunctions method, which is based upon a
225+
* query, rather than hard coding the oid. The oid for a function is not
226+
* guaranteed to remain static, even on different servers of the same
227+
* version.
228+
*
229+
* @param name Function name
230+
* @param fnid Function id
231+
*/
232+
publicvoidaddFunction(Stringname,intfnid)
233+
{
234+
func.put(name,newInteger(fnid));
235+
}
236+
237+
/**
238+
* This takes a ResultSet containing two columns. Column 1 contains the
239+
* function name, Column 2 the oid.
240+
*
241+
* <p>It reads the entire ResultSet, loading the values into the function
242+
* table.
243+
*
244+
* <p><b>REMEMBER</b> to close() the resultset after calling this!!
245+
*
246+
* <p><b><em>Implementation note about function name lookups:</em></b>
247+
*
248+
* <p>PostgreSQL stores the function id's and their corresponding names in
249+
* the pg_proc table. To speed things up locally, instead of querying each
250+
* function from that table when required, a Hashtable is used. Also, only
251+
* the function's required are entered into this table, keeping connection
252+
* times as fast as possible.
253+
*
254+
* <p>The org.postgresql.LargeObject class performs a query upon it's startup,
255+
* and passes the returned ResultSet to the addFunctions() method here.
256+
*
257+
* <p>Once this has been done, the LargeObject api refers to the functions by
258+
* name.
259+
*
260+
* <p>Dont think that manually converting them to the oid's will work. Ok,
261+
* they will for now, but they can change during development (there was some
262+
* discussion about this for V7.0), so this is implemented to prevent any
263+
* unwarranted headaches in the future.
264+
*
265+
* @param rs ResultSet
266+
* @exception SQLException if a database-access error occurs.
267+
* @see org.postgresql.LargeObjectManager
268+
*/
269+
publicvoidaddFunctions(ResultSetrs)throwsSQLException
270+
{
271+
while(rs.next()) {
272+
func.put(rs.getString(1),newInteger(rs.getInt(2)));
273+
}
274+
}
275+
276+
/**
277+
* This returns the function id associated by its name
278+
*
279+
* <p>If addFunction() or addFunctions() have not been called for this name,
280+
* then an SQLException is thrown.
281+
*
282+
* @param name Function name to lookup
283+
* @return Function ID for fastpath call
284+
* @exception SQLException is function is unknown.
285+
*/
286+
publicintgetID(Stringname)throwsSQLException
287+
{
288+
Integerid = (Integer)func.get(name);
289+
290+
// may be we could add a lookup to the database here, and store the result
291+
// in our lookup table, throwing the exception if that fails.
292+
// We must, however, ensure that if we do, any existing ResultSet is
293+
// unaffected, otherwise we could break user code.
294+
//
295+
// so, until we know we can do this (needs testing, on the TODO list)
296+
// for now, we throw the exception and do no lookups.
297+
if(id==null)
298+
thrownewPSQLException("postgresql.fp.unknown",name);
299+
300+
returnid.intValue();
301+
}
302+
}
303+

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp