Hi,
I’m implementing the functionality that will pass all the queries native to
postgresql (that asks about structures and versions) to the hidden postgresql
and other queries I would like to parse myself. I have a big problem with
outputing PG_TYPE_INT[248] value. I’m doing it because in my system I would
like to provide the method to send by jdbc XML messages that would be resolved
by my software and other queries would be answered by PostgreSQL. I don’t mind
the speed and the double processing I just want to learn how to do it.
Outputing texts works fine.
So when I receive native query like (select * from pg_class) I have active JDBC
connection to hidden postgresql (9.3) and this query is executed on that
server. When I get ResultSet from the hidden postgresql I try to output the
results in postgres form to the output. Example communication that returns
current date in long (in my opinion) should look like this:
//Example code that outputs current date in long format
public void sendExampleResponse() {
server.trace("Query");
String query = readString();
System.out.println("query = " + query);
long timeLong = new java.util.Date().getTime();
startMessage('T');
writeShort(1); //column amount
writeString("TEST”); //column name
writeInt(0); //object ID
writeShort(0); // attribute number of the column (i tested by changing
it to 1 or so didn’t work)
writeInt(PG_TYPE_INT8); //type of the data - PG_TYPE_INT8
int size = 8;
System.out.println("size: "+size);
writeShort(size); //the size of this type
writeInt(-1); pg_attribute.atttypmod
writeShort(0);//the form of 0 ? text : binary
sendMessage();
startMessage('D’); //start outputing results
writeShort(1); //column quantity
int longSizeBytes=8;
System.out.println("writeLongSize: "+longSizeBytes);
writeInt(longSizeBytes);
writeLong(timeLong);
sendCommandComplete(COMMAND_TYPE.SELECT, 4);
sendReadyForQuery();
}
WriteInt (the type of out variable is OutputStream):
It is from DataOutputStream:
public final void writeInt(int v) throws IOException {
out.write((v >>> 24) & 0xFF);
out.write((v >>> 16) & 0xFF);
out.write((v >>> 8) & 0xFF);
out.write((v >>> 0) & 0xFF);
incCount(4);
}
WriteShort:
public final void writeShort(int v) throws IOException {
out.write((v >>> 8) & 0xFF);
out.write((v >>> 0) & 0xFF);
incCount(2);
}
WriteLong:
private byte writeBuffer[] = new byte[8];
public final void writeLong(long v) throws IOException {
writeBuffer[0] = (byte)(v >>> 56);
writeBuffer[1] = (byte)(v >>> 48);
writeBuffer[2] = (byte)(v >>> 40);
writeBuffer[3] = (byte)(v >>> 32);
writeBuffer[4] = (byte)(v >>> 24);
writeBuffer[5] = (byte)(v >>> 16);
writeBuffer[6] = (byte)(v >>> 8);
writeBuffer[7] = (byte)(v >>> 0);
out.write(writeBuffer, 0, 8);
incCount(8);
}
I did do some tests like sending 10000 times these same query that outputs what
is in example changing the variable size and longSizeBytes (for 1
incrementation of size there were 100 of longSizeBytes). I checked everything.
Even I analyzed the code of sendInt in PostgreSQL source code. I don’t know
what to do more. Could someone help me with changing sendExampleResponse?
BTW I’m checking how it works by connecting to my custom server using psql but
the results of queries like (select test form test;) is outputted by
sendExampleResponse method. \l works, \d works \d <tableName> doesn’t work.
PSQL has two queries in \d <tableName>. Fist one returns oid of the table and
second one outputs columns using this oid. Because OID is number (java object
java.lang.Long) I can’t do much more than \l, \d :) on my custom server.
Krystian