private void sendRowDescription(ResultSetMetaData meta) throws Exception { if (meta == null) { sendNoData(); } else { int columns = meta.getColumnCount(); int[] types = new int[columns]; int[] precision = new int[columns]; String[] names = new String[columns]; for (int i = 0; i < columns; i++) { String name = meta.getColumnName(i + 1); names[i] = name; int type = meta.getColumnType(i + 1); type = PgServer.convertType(type); // the ODBC client needs the column pg_catalog.pg_index // to be of type 'int2vector' // if (name.equalsIgnoreCase("indkey") && // "pg_index".equalsIgnoreCase(meta.getTableName(i + 1))) { // type = PgServer.PG_TYPE_INT2VECTOR; // } precision[i] = meta.getColumnDisplaySize(i + 1); server.checkType(type); types[i] = type; } startMessage('T'); writeShort(columns); for (int i = 0; i < columns; i++) { writeString(StringUtils.toLowerEnglish(names[i])); // object ID writeInt(0); // attribute number of the column writeShort(0); // data type writeInt(types[i]); // pg_type.typlen writeShort(getTypeSize(types[i], precision[i])); // pg_attribute.atttypmod writeInt(-1); // text writeShort(0); } sendMessage(); } }
private void sendParameterDescription(Prepared p) throws IOException { try { PreparedStatement prep = p.prep; ParameterMetaData meta = prep.getParameterMetaData(); int count = meta.getParameterCount(); startMessage('t'); writeShort(count); for (int i = 0; i < count; i++) { int type; if (p.paramType != null && p.paramType[i] != 0) { type = p.paramType[i]; } else { type = PgServer.PG_TYPE_VARCHAR; } server.checkType(type); writeInt(type); } sendMessage(); } catch (Exception e) { sendErrorResponse(e); } }
private void process() throws IOException { int x; if (initDone) { x = dataInRaw.read(); if (x < 0) { stop = true; return; } } else { x = 0; } int len = dataInRaw.readInt(); len -= 4; byte[] data = DataUtils.newBytes(len); dataInRaw.readFully(data, 0, len); dataIn = new DataInputStream(new ByteArrayInputStream(data, 0, len)); switchBlock: switch (x) { case 0: server.trace("Init"); int version = readInt(); if (version == 80877102) { server.trace("CancelRequest (not supported)"); server.trace(" pid: " + readInt()); server.trace(" key: " + readInt()); } else if (version == 80877103) { server.trace("SSLRequest"); out.write('N'); } else { server.trace("StartupMessage"); server.trace( " version " + version + " (" + (version >> 16) + "." + (version & 0xff) + ")"); while (true) { String param = readString(); if (param.length() == 0) { break; } String value = readString(); if ("user".equals(param)) { this.userName = value; } else if ("database".equals(param)) { this.databaseName = value; } else if ("client_encoding".equals(param)) { // UTF8 clientEncoding = value; } else if ("DateStyle".equals(param)) { dateStyle = value; } // extra_float_digits 2 // geqo on (Genetic Query Optimization) server.trace(" param " + param + "=" + value); } sendAuthenticationCleartextPassword(); initDone = true; } break; case 'p': { server.trace("PasswordMessage"); String password = readString(); try { // Properties info = new Properties(); // info.put("MODE", "PostgreSQL"); // info.put("USER", userName); // info.put("PASSWORD", password); // String url = "jdbc:lealone:" + databaseName; // ConnectionInfo ci = new ConnectionInfo(url, info); // String baseDir = server.getBaseDir(); // if (baseDir == null) { // baseDir = SysProperties.getBaseDir(); // } // if (baseDir != null) { // ci.setBaseDir(baseDir); // } // if (server.getIfExists()) { // ci.setProperty("IFEXISTS", "TRUE"); // } // conn = new JdbcConnection(ci, false); conn = createJdbcConnection(password); // can not do this because when called inside // DriverManager.getConnection, a deadlock occurs // conn = DriverManager.getConnection(url, userName, password); initDb(); sendAuthenticationOk(); } catch (Exception e) { e.printStackTrace(); stop = true; } break; } case 'P': { server.trace("Parse"); Prepared p = new Prepared(); p.name = readString(); p.sql = getSQL(readString()); int count = readShort(); p.paramType = new int[count]; for (int i = 0; i < count; i++) { int type = readInt(); server.checkType(type); p.paramType[i] = type; } try { p.prep = (JdbcPreparedStatement) conn.prepareStatement(p.sql); prepared.put(p.name, p); sendParseComplete(); } catch (Exception e) { sendErrorResponse(e); } break; } case 'B': { server.trace("Bind"); Portal portal = new Portal(); portal.name = readString(); String prepName = readString(); Prepared prep = prepared.get(prepName); if (prep == null) { sendErrorResponse("Prepared not found"); break; } portal.prep = prep; portals.put(portal.name, portal); int formatCodeCount = readShort(); int[] formatCodes = new int[formatCodeCount]; for (int i = 0; i < formatCodeCount; i++) { formatCodes[i] = readShort(); } int paramCount = readShort(); for (int i = 0; i < paramCount; i++) { int paramLen = readInt(); byte[] d2 = DataUtils.newBytes(paramLen); readFully(d2); try { setParameter(prep.prep, i, d2, formatCodes); } catch (Exception e) { sendErrorResponse(e); break switchBlock; } } int resultCodeCount = readShort(); portal.resultColumnFormat = new int[resultCodeCount]; for (int i = 0; i < resultCodeCount; i++) { portal.resultColumnFormat[i] = readShort(); } sendBindComplete(); break; } case 'C': { char type = (char) readByte(); String name = readString(); server.trace("Close"); if (type == 'S') { Prepared p = prepared.remove(name); if (p != null) { JdbcUtils.closeSilently(p.prep); } } else if (type == 'P') { portals.remove(name); } else { server.trace("expected S or P, got " + type); sendErrorResponse("expected S or P"); break; } sendCloseComplete(); break; } case 'D': { char type = (char) readByte(); String name = readString(); server.trace("Describe"); if (type == 'S') { Prepared p = prepared.get(name); if (p == null) { sendErrorResponse("Prepared not found: " + name); } else { sendParameterDescription(p); } } else if (type == 'P') { Portal p = portals.get(name); if (p == null) { sendErrorResponse("Portal not found: " + name); } else { PreparedStatement prep = p.prep.prep; try { ResultSetMetaData meta = prep.getMetaData(); sendRowDescription(meta); } catch (Exception e) { sendErrorResponse(e); } } } else { server.trace("expected S or P, got " + type); sendErrorResponse("expected S or P"); } break; } case 'E': { String name = readString(); server.trace("Execute"); Portal p = portals.get(name); if (p == null) { sendErrorResponse("Portal not found: " + name); break; } int maxRows = readShort(); Prepared prepared = p.prep; JdbcPreparedStatement prep = prepared.prep; server.trace(prepared.sql); try { prep.setMaxRows(maxRows); boolean result = prep.execute(); if (result) { try { ResultSet rs = prep.getResultSet(); ResultSetMetaData meta = rs.getMetaData(); sendRowDescription(meta); while (rs.next()) { sendDataRow(rs); } sendCommandComplete(prep, 0); } catch (Exception e) { sendErrorResponse(e); } } else { sendCommandComplete(prep, prep.getUpdateCount()); } } catch (Exception e) { sendErrorResponse(e); } break; } case 'S': { server.trace("Sync"); sendReadyForQuery(); break; } case 'Q': { server.trace("Query"); String query = readString(); ScriptReader reader = new ScriptReader(new StringReader(query)); while (true) { JdbcStatement stat = null; try { String s = reader.readStatement(); if (s == null) { break; } s = getSQL(s); stat = (JdbcStatement) conn.createStatement(); boolean result = stat.execute(s); if (result) { ResultSet rs = stat.getResultSet(); ResultSetMetaData meta = rs.getMetaData(); try { sendRowDescription(meta); while (rs.next()) { sendDataRow(rs); } sendCommandComplete(stat, 0); } catch (Exception e) { sendErrorResponse(e); break; } } else { sendCommandComplete(stat, stat.getUpdateCount()); } } catch (SQLException e) { sendErrorResponse(e); break; } finally { JdbcUtils.closeSilently(stat); } } sendReadyForQuery(); break; } case 'X': { server.trace("Terminate"); close(); break; } default: server.trace("Unsupported: " + x + " (" + (char) x + ")"); break; } }