Skip to content

Commit d6e0ee6

Browse files
committed
Added missing file.
1 parent 0f356be commit d6e0ee6

File tree

2 files changed

+344
-1
lines changed

2 files changed

+344
-1
lines changed
Lines changed: 342 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,342 @@
1+
package postgresql.util;
2+
3+
import java.io.*;
4+
import java.lang.*;
5+
import java.lang.reflect.*;
6+
import java.net.*;
7+
import java.util.*;
8+
import java.sql.*;
9+
10+
/**
11+
* This class uses PostgreSQL's object oriented features to store Java Objects.
12+
*
13+
* It does this by mapping a Java Class name to a table in the database. Each
14+
* entry in this new table then represents a Serialized instance of this
15+
* class. As each entry has an OID (Object IDentifier), this OID can be
16+
* included in another table.
17+
*
18+
* This is too complex to show here, and will be documented in the main
19+
* documents in more detail.
20+
*
21+
*/
22+
public class Serialize
23+
{
24+
// This is the connection that the instance refers to
25+
protected postgresql.Connection conn;
26+
27+
// This is the table name
28+
protected String tableName;
29+
30+
// This is the class name
31+
protected String className;
32+
33+
// This is the Class for this serialzed object
34+
protected Class ourClass;
35+
36+
/**
37+
* This creates an instance that can be used to serialize or deserialize
38+
* a Java object from a PostgreSQL table.
39+
*/
40+
public Serialize(postgresql.Connection c,String type) throws SQLException
41+
{
42+
try {
43+
conn = c;
44+
tableName = type.toLowerCase();
45+
className = toClassName(type);
46+
ourClass = Class.forName(className);
47+
} catch(ClassNotFoundException cnfe) {
48+
throw new SQLException("No class found for '"+type+"`");
49+
}
50+
51+
// Second check, the type must be a table
52+
boolean status = false;
53+
ResultSet rs = conn.ExecSQL("select typname from pg_type,pg_class where typname=relname and typname='"+type+"'");
54+
if(rs!=null) {
55+
if(rs.next())
56+
status=true;
57+
rs.close();
58+
}
59+
// This should never occur, as postgresql has it's own internal checks
60+
if(!status)
61+
throw new SQLException("The table for "+type+" is not in the database. Contact the DBA, as the database is in an inconsistent state.");
62+
63+
// Finally cache the fields within the table
64+
}
65+
66+
/**
67+
* This fetches an object from a table, given it's OID
68+
* @param oid The oid of the object
69+
* @return Object relating to oid
70+
* @exception SQLException on error
71+
*/
72+
public Object fetch(int oid) throws SQLException
73+
{
74+
try {
75+
Object obj = ourClass.newInstance();
76+
77+
// NB: we use java.lang.reflect here to prevent confusion with
78+
// the postgresql.Field
79+
java.lang.reflect.Field f[] = ourClass.getDeclaredFields();
80+
boolean hasOID=false;
81+
int oidFIELD=-1;
82+
StringBuffer sb = new StringBuffer("select");
83+
char sep=' ';
84+
for(int i=0;i<f.length;i++) {
85+
String n = f[i].getName();
86+
if(n.equals("oid")) {
87+
hasOID=true;
88+
oidFIELD=i;
89+
}
90+
sb.append(sep);
91+
sb.append(n);
92+
sep=',';
93+
}
94+
sb.append(" from ");
95+
sb.append(tableName);
96+
sb.append(" where oid=");
97+
sb.append(oid);
98+
99+
DriverManager.println("store: "+sb.toString());
100+
ResultSet rs = conn.ExecSQL(sb.toString());
101+
if(rs!=null) {
102+
if(rs.next()) {
103+
for(int i=0;i<f.length;i++) {
104+
f[i].set(obj,rs.getObject(i+1));
105+
}
106+
}
107+
rs.close();
108+
} else
109+
throw new SQLException("Unexpected result from query");
110+
return obj;
111+
} catch(IllegalAccessException iae) {
112+
throw new SQLException(iae.toString());
113+
} catch(InstantiationException ie) {
114+
throw new SQLException(ie.toString());
115+
}
116+
}
117+
118+
/**
119+
* This stores an object into a table, returning it's OID.<p>
120+
*
121+
* If the object has an int called OID, and it is > 0, then
122+
* that value is used for the OID, and the table will be updated.
123+
* If the value of OID is 0, then a new row will be created, and the
124+
* value of OID will be set in the object. This enables an object's
125+
* value in the database to be updateable.
126+
*
127+
* If the object has no int called OID, then the object is stored. However
128+
* if the object is later retrieved, amended and stored again, it's new
129+
* state will be appended to the table, and will not overwrite the old
130+
* entries.
131+
*
132+
* @param o Object to store (must implement Serializable)
133+
* @return oid of stored object
134+
* @exception SQLException on error
135+
*/
136+
public int store(Object o) throws SQLException
137+
{
138+
try {
139+
// NB: we use java.lang.reflect here to prevent confusion with
140+
// the postgresql.Field
141+
java.lang.reflect.Field f[] = ourClass.getDeclaredFields();
142+
boolean hasOID=false;
143+
int oidFIELD=-1;
144+
boolean update=false;
145+
146+
// Find out if we have an oid value
147+
for(int i=0;i<f.length;i++) {
148+
String n = f[i].getName();
149+
if(n.equals("oid")) {
150+
hasOID=true;
151+
oidFIELD=i;
152+
153+
// We are an update if oid != 0
154+
update = f[i].getInt(o)>0;
155+
}
156+
}
157+
158+
StringBuffer sb = new StringBuffer(update?"update "+tableName+" set":"insert into "+tableName+" values ");
159+
char sep=update?' ':'(';
160+
for(int i=0;i<f.length;i++) {
161+
String n = f[i].getName();
162+
sb.append(sep);
163+
sb.append(n);
164+
sep=',';
165+
if(update) {
166+
sb.append('=');
167+
if(f[i].getType().getName().equals("java.lang.String")) {
168+
sb.append('\'');
169+
sb.append(f[i].get(o).toString());
170+
sb.append('\'');
171+
} else
172+
sb.append(f[i].get(o).toString());
173+
}
174+
}
175+
176+
if(!update) {
177+
sb.append(") values ");
178+
sep='(';
179+
for(int i=0;i<f.length;i++) {
180+
String n = f[i].getName();
181+
if(f[i].getType().getName().equals("java.lang.String")) {
182+
sb.append('\'');
183+
sb.append(f[i].get(o).toString());
184+
sb.append('\'');
185+
} else
186+
sb.append(f[i].get(o).toString());
187+
}
188+
sb.append(')');
189+
}
190+
191+
DriverManager.println("store: "+sb.toString());
192+
ResultSet rs = conn.ExecSQL(sb.toString());
193+
if(rs!=null) {
194+
rs.close();
195+
}
196+
197+
// fetch the OID for returning
198+
int oid=0;
199+
if(hasOID) {
200+
// set the oid in the object
201+
f[oidFIELD].setInt(o,oid);
202+
}
203+
return oid;
204+
205+
} catch(IllegalAccessException iae) {
206+
throw new SQLException(iae.toString());
207+
}
208+
}
209+
210+
/**
211+
* This method is not used by the driver, but it creates a table, given
212+
* a Serializable Java Object. It should be used before serializing any
213+
* objects.
214+
* @param c Connection to database
215+
* @param o Object to base table on
216+
* @exception SQLException on error
217+
*/
218+
public static void create(postgresql.Connection con,Object o) throws SQLException
219+
{
220+
create(con,o.getClass());
221+
}
222+
223+
/**
224+
* This method is not used by the driver, but it creates a table, given
225+
* a Serializable Java Object. It should be used before serializing any
226+
* objects.
227+
* @param c Connection to database
228+
* @param o Class to base table on
229+
* @exception SQLException on error
230+
*/
231+
public static void create(postgresql.Connection con,Class c) throws SQLException
232+
{
233+
if(c.isInterface())
234+
throw new SQLException("Cannot serialize an Interface");
235+
236+
// See if the table exists
237+
String tableName = toPostgreSQL(c.getName());
238+
239+
ResultSet rs = con.ExecSQL("select relname from pg_class where relname = '"+tableName+"'");
240+
if(!rs.next()) {
241+
DriverManager.println("found "+rs.getString(1));
242+
// No entries returned, so the table doesn't exist
243+
244+
StringBuffer sb = new StringBuffer("create table ");
245+
sb.append(tableName);
246+
char sep='(';
247+
248+
java.lang.reflect.Field[] fields = c.getDeclaredFields();
249+
for(int i=0;i<fields.length;i++) {
250+
Class type = fields[i].getType();
251+
252+
// oid is a special field
253+
if(!fields[i].getName().equals("oid")) {
254+
sb.append(sep);
255+
sb.append(fields[i].getName());
256+
sb.append(' ');
257+
sep=',';
258+
259+
if(type.isArray()) {
260+
// array handling
261+
} else {
262+
// convert the java type to postgresql, recursing if a class
263+
// is found
264+
String n = fields[i].getType().getName();
265+
int j=0;
266+
for(;j<tp.length && !tp[j][0].equals(n);j++);
267+
if(j<tp.length)
268+
sb.append(tp[j][1]);
269+
else {
270+
create(con,fields[i].getType());
271+
sb.append(toPostgreSQL(n));
272+
}
273+
}
274+
}
275+
}
276+
sb.append(")");
277+
278+
// Now create the table
279+
DriverManager.println("Serialize.create:"+sb);
280+
con.ExecSQL(sb.toString());
281+
rs.close();
282+
} else {
283+
DriverManager.println("Serialize.create: table "+tableName+" exists, skipping");
284+
}
285+
}
286+
287+
// This is used to translate between Java primitives and PostgreSQL types.
288+
private static final String tp[][] = {
289+
{"boolean", "int1"},
290+
{"double", "float8"},
291+
{"float", "float4"},
292+
{"int", "int4"},
293+
{"long", "int4"},
294+
{"short", "int2"},
295+
{"java.lang.String", "text"},
296+
{"java.lang.Integer", "int4"},
297+
{"java.lang.Float", "float4"},
298+
{"java.lang.Double", "float8"},
299+
{"java.lang.Short", "int2"}
300+
};
301+
302+
/**
303+
* This converts a Java Class name to a postgresql table, by replacing . with
304+
* _<p>
305+
*
306+
* Because of this, a Class name may not have _ in the name.<p>
307+
* Another limitation, is that the entire class name (including packages)
308+
* cannot be longer than 32 characters (a limit forced by PostgreSQL).
309+
*
310+
* @param name Class name
311+
* @return PostgreSQL table name
312+
* @exception SQLException on error
313+
*/
314+
public static String toPostgreSQL(String name) throws SQLException
315+
{
316+
name = name.toLowerCase();
317+
318+
if(name.indexOf("_")>-1)
319+
throw new SQLException("Class names may not have _ in them: "+name);
320+
321+
if(name.length()>32)
322+
throw new SQLException("Class & Package name length cannot be longer than 32 characters. "+name+" is "+name.length()+" characters.");
323+
324+
return name.replace('.','_');
325+
}
326+
327+
328+
/**
329+
* This converts a postgresql table to a Java Class name, by replacing _ with
330+
* .<p>
331+
*
332+
* @param name PostgreSQL table name
333+
* @return Class name
334+
* @exception SQLException on error
335+
*/
336+
public static String toClassName(String name) throws SQLException
337+
{
338+
name = name.toLowerCase();
339+
return name.replace('_','.');
340+
}
341+
342+
}

src/interfaces/libpq/fe-print.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99
* didn't really belong there.
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-print.c,v 1.3 1998/06/15 19:30:26 momjian Exp $
12+
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-print.c,v 1.4 1998/06/16 06:57:27 momjian Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
16+
#include <postgres.h>
1617
#include <stdlib.h>
1718
#include <stdio.h>
1819
#include <signal.h>

0 commit comments

Comments
 (0)