Search in sources :

Example 11 with ConnectionInfo

use of org.h2.engine.ConnectionInfo in project h2database by h2database.

the class DbUpgrade method connectOrUpgrade.

/**
 * If the upgrade classes are present, upgrade the database, or connect
 * using the old version (if the parameter NO_UPGRADE is set to true). If
 * the database is upgraded, or if no upgrade is possible or needed, this
 * methods returns null.
 *
 * @param url the database URL
 * @param info the properties
 * @return the connection if connected with the old version (NO_UPGRADE)
 */
public static Connection connectOrUpgrade(String url, Properties info) throws SQLException {
    if (!UPGRADE_CLASSES_PRESENT) {
        return null;
    }
    Properties i2 = new Properties();
    i2.putAll(info);
    // clone so that the password (if set as a char array) is not cleared
    Object o = info.get("password");
    if (o instanceof char[]) {
        i2.put("password", StringUtils.cloneCharArray((char[]) o));
    }
    info = i2;
    ConnectionInfo ci = new ConnectionInfo(url, info);
    if (ci.isRemote() || !ci.isPersistent()) {
        return null;
    }
    String name = ci.getName();
    if (FileUtils.exists(name + Constants.SUFFIX_PAGE_FILE)) {
        return null;
    }
    if (!FileUtils.exists(name + Constants.SUFFIX_OLD_DATABASE_FILE)) {
        return null;
    }
    if (ci.removeProperty("NO_UPGRADE", false)) {
        return connectWithOldVersion(url, info);
    }
    synchronized (DbUpgrade.class) {
        upgrade(ci, info);
        return null;
    }
}
Also used : ConnectionInfo(org.h2.engine.ConnectionInfo) Properties(java.util.Properties)

Example 12 with ConnectionInfo

use of org.h2.engine.ConnectionInfo in project h2database by h2database.

the class Engine method openSession.

private Session openSession(ConnectionInfo ci, boolean ifExists, String cipher) {
    String name = ci.getName();
    Database database;
    ci.removeProperty("NO_UPGRADE", false);
    boolean openNew = ci.getProperty("OPEN_NEW", false);
    boolean opened = false;
    User user = null;
    synchronized (DATABASES) {
        if (openNew || ci.isUnnamedInMemory()) {
            database = null;
        } else {
            database = DATABASES.get(name);
        }
        if (database == null) {
            if (ifExists && !Database.exists(name)) {
                throw DbException.get(ErrorCode.DATABASE_NOT_FOUND_1, name);
            }
            database = new Database(ci, cipher);
            opened = true;
            if (database.getAllUsers().isEmpty()) {
                // users is the last thing we add, so if no user is around,
                // the database is new (or not initialized correctly)
                user = new User(database, database.allocateObjectId(), ci.getUserName(), false);
                user.setAdmin(true);
                user.setUserPasswordHash(ci.getUserPasswordHash());
                database.setMasterUser(user);
            }
            if (!ci.isUnnamedInMemory()) {
                DATABASES.put(name, database);
            }
        }
    }
    if (opened) {
        // start the thread when already synchronizing on the database
        // otherwise a deadlock can occur when the writer thread
        // opens a new database (as in recovery testing)
        database.opened();
    }
    if (database.isClosing()) {
        return null;
    }
    if (user == null) {
        if (database.validateFilePasswordHash(cipher, ci.getFilePasswordHash())) {
            user = database.findUser(ci.getUserName());
            if (user != null) {
                if (!user.validateUserPasswordHash(ci.getUserPasswordHash())) {
                    user = null;
                }
            }
        }
        if (opened && (user == null || !user.isAdmin())) {
            // reset - because the user is not an admin, and has no
            // right to listen to exceptions
            database.setEventListener(null);
        }
    }
    if (user == null) {
        DbException er = DbException.get(ErrorCode.WRONG_USER_OR_PASSWORD);
        database.getTrace(Trace.DATABASE).error(er, "wrong user or password; user: \"" + ci.getUserName() + "\"");
        database.removeSession(null);
        throw er;
    }
    checkClustering(ci, database);
    Session session = database.createSession(user);
    if (session == null) {
        // concurrently closing
        return null;
    }
    if (ci.getProperty("JMX", false)) {
        try {
            Utils.callStaticMethod("org.h2.jmx.DatabaseInfo.registerMBean", ci, database);
        } catch (Exception e) {
            database.removeSession(session);
            throw DbException.get(ErrorCode.FEATURE_NOT_SUPPORTED_1, e, "JMX");
        }
        jmx = true;
    }
    return session;
}
Also used : DbException(org.h2.message.DbException) DbException(org.h2.message.DbException)

Example 13 with ConnectionInfo

use of org.h2.engine.ConnectionInfo in project h2database by h2database.

the class Engine method openSession.

private synchronized Session openSession(ConnectionInfo ci) {
    boolean ifExists = ci.removeProperty("IFEXISTS", false);
    boolean ignoreUnknownSetting = ci.removeProperty("IGNORE_UNKNOWN_SETTINGS", false);
    String cipher = ci.removeProperty("CIPHER", null);
    String init = ci.removeProperty("INIT", null);
    Session session;
    for (int i = 0; ; i++) {
        session = openSession(ci, ifExists, cipher);
        if (session != null) {
            break;
        }
        // wait a bit to avoid a busy loop (the method is synchronized)
        if (i > 60 * 1000) {
            // retry at most 1 minute
            throw DbException.get(ErrorCode.DATABASE_ALREADY_OPEN_1, "Waited for database closing longer than 1 minute");
        }
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
        // ignore
        }
    }
    synchronized (session) {
        session.setAllowLiterals(true);
        DbSettings defaultSettings = DbSettings.getDefaultSettings();
        for (String setting : ci.getKeys()) {
            if (defaultSettings.containsKey(setting)) {
                // database setting are only used when opening the database
                continue;
            }
            String value = ci.getProperty(setting);
            try {
                CommandInterface command = session.prepareCommand("SET " + Parser.quoteIdentifier(setting) + " " + value, Integer.MAX_VALUE);
                command.executeUpdate(false);
            } catch (DbException e) {
                if (e.getErrorCode() == ErrorCode.ADMIN_RIGHTS_REQUIRED) {
                    session.getTrace().error(e, "admin rights required; user: \"" + ci.getUserName() + "\"");
                } else {
                    session.getTrace().error(e, "");
                }
                if (!ignoreUnknownSetting) {
                    session.close();
                    throw e;
                }
            }
        }
        if (init != null) {
            try {
                CommandInterface command = session.prepareCommand(init, Integer.MAX_VALUE);
                command.executeUpdate(false);
            } catch (DbException e) {
                if (!ignoreUnknownSetting) {
                    session.close();
                    throw e;
                }
            }
        }
        session.setAllowLiterals(false);
        session.commit(true);
    }
    return session;
}
Also used : CommandInterface(org.h2.command.CommandInterface) DbException(org.h2.message.DbException)

Example 14 with ConnectionInfo

use of org.h2.engine.ConnectionInfo in project h2database by h2database.

the class SessionRemote method initTransfer.

private Transfer initTransfer(ConnectionInfo ci, String db, String server) throws IOException {
    Socket socket = NetUtils.createSocket(server, Constants.DEFAULT_TCP_PORT, ci.isSSL());
    Transfer trans = new Transfer(this, socket);
    trans.setSSL(ci.isSSL());
    trans.init();
    trans.writeInt(Constants.TCP_PROTOCOL_VERSION_MIN_SUPPORTED);
    trans.writeInt(Constants.TCP_PROTOCOL_VERSION_MAX_SUPPORTED);
    trans.writeString(db);
    trans.writeString(ci.getOriginalURL());
    trans.writeString(ci.getUserName());
    trans.writeBytes(ci.getUserPasswordHash());
    trans.writeBytes(ci.getFilePasswordHash());
    String[] keys = ci.getKeys();
    trans.writeInt(keys.length);
    for (String key : keys) {
        trans.writeString(key).writeString(ci.getProperty(key));
    }
    try {
        done(trans);
        clientVersion = trans.readInt();
        trans.setVersion(clientVersion);
        if (clientVersion >= Constants.TCP_PROTOCOL_VERSION_14) {
            if (ci.getFileEncryptionKey() != null) {
                trans.writeBytes(ci.getFileEncryptionKey());
            }
        }
        trans.writeInt(SessionRemote.SESSION_SET_ID);
        trans.writeString(sessionId);
        done(trans);
        if (clientVersion >= Constants.TCP_PROTOCOL_VERSION_15) {
            autoCommit = trans.readBoolean();
        } else {
            autoCommit = true;
        }
        return trans;
    } catch (DbException e) {
        trans.close();
        throw e;
    }
}
Also used : Transfer(org.h2.value.Transfer) Socket(java.net.Socket) DbException(org.h2.message.DbException)

Example 15 with ConnectionInfo

use of org.h2.engine.ConnectionInfo in project h2database by h2database.

the class PgServerThread method process.

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 = Utils.newBytes(len);
    dataInRaw.readFully(data, 0, len);
    dataIn = new DataInputStream(new ByteArrayInputStream(data, 0, len));
    switch(x) {
        case 0:
            server.trace("Init");
            int version = readInt();
            if (version == 80877102) {
                server.trace("CancelRequest");
                int pid = readInt();
                int key = readInt();
                PgServerThread c = server.getThread(pid);
                if (c != null && key == c.secret) {
                    c.cancelRequest();
                } else {
                    // According to the PostgreSQL documentation, when canceling
                    // a request, if an invalid secret is provided then no
                    // exception should be sent back to the client.
                    server.trace("Invalid CancelRequest: pid=" + pid + ", key=" + key);
                }
                close();
            } 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 = server.checkKeyAndGetDatabaseName(value);
                    } else if ("client_encoding".equals(param)) {
                        // UTF8
                        clientEncoding = value;
                    } else if ("DateStyle".equals(param)) {
                        if (value.indexOf(',') < 0) {
                            value += ", MDY";
                        }
                        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:h2:" + 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);
                    // 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 paramTypesCount = readShort();
                int[] paramTypes = null;
                if (paramTypesCount > 0) {
                    paramTypes = new int[paramTypesCount];
                    for (int i = 0; i < paramTypesCount; i++) {
                        paramTypes[i] = readInt();
                    }
                }
                try {
                    p.prep = (JdbcPreparedStatement) conn.prepareStatement(p.sql);
                    ParameterMetaData meta = p.prep.getParameterMetaData();
                    p.paramType = new int[meta.getParameterCount()];
                    for (int i = 0; i < p.paramType.length; i++) {
                        int type;
                        if (i < paramTypesCount && paramTypes[i] != 0) {
                            type = paramTypes[i];
                            server.checkType(type);
                        } else {
                            type = PgServer.convertType(meta.getParameterType(i + 1));
                        }
                        p.paramType[i] = type;
                    }
                    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();
                try {
                    for (int i = 0; i < paramCount; i++) {
                        setParameter(prep.prep, prep.paramType[i], i, formatCodes);
                    }
                } catch (Exception e) {
                    sendErrorResponse(e);
                    break;
                }
                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 {
                        try {
                            sendParameterDescription(p.prep.getParameterMetaData(), p.paramType);
                            sendRowDescription(p.prep.getMetaData());
                        } catch (Exception e) {
                            sendErrorResponse(e);
                        }
                    }
                } 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);
                    setActiveRequest(prep);
                    boolean result = prep.execute();
                    if (result) {
                        try {
                            ResultSet rs = prep.getResultSet();
                            // the meta-data is sent in the prior 'Describe'
                            while (rs.next()) {
                                sendDataRow(rs, p.resultColumnFormat);
                            }
                            sendCommandComplete(prep, 0);
                        } catch (Exception e) {
                            sendErrorResponse(e);
                        }
                    } else {
                        sendCommandComplete(prep, prep.getUpdateCount());
                    }
                } catch (Exception e) {
                    if (prep.isCancelled()) {
                        sendCancelQueryResponse();
                    } else {
                        sendErrorResponse(e);
                    }
                } finally {
                    setActiveRequest(null);
                }
                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();
                        setActiveRequest(stat);
                        boolean result = stat.execute(s);
                        if (result) {
                            ResultSet rs = stat.getResultSet();
                            ResultSetMetaData meta = rs.getMetaData();
                            try {
                                sendRowDescription(meta);
                                while (rs.next()) {
                                    sendDataRow(rs, null);
                                }
                                sendCommandComplete(stat, 0);
                            } catch (Exception e) {
                                sendErrorResponse(e);
                                break;
                            }
                        } else {
                            sendCommandComplete(stat, stat.getUpdateCount());
                        }
                    } catch (SQLException e) {
                        if (stat != null && stat.isCancelled()) {
                            sendCancelQueryResponse();
                        } else {
                            sendErrorResponse(e);
                        }
                        break;
                    } finally {
                        JdbcUtils.closeSilently(stat);
                        setActiveRequest(null);
                    }
                }
                sendReadyForQuery();
                break;
            }
        case 'X':
            {
                server.trace("Terminate");
                close();
                break;
            }
        default:
            server.trace("Unsupported: " + x + " (" + (char) x + ")");
            break;
    }
}
Also used : SQLException(java.sql.SQLException) JdbcConnection(org.h2.jdbc.JdbcConnection) PreparedStatement(java.sql.PreparedStatement) JdbcPreparedStatement(org.h2.jdbc.JdbcPreparedStatement) DataInputStream(java.io.DataInputStream) SysProperties(org.h2.engine.SysProperties) Properties(java.util.Properties) DbException(org.h2.message.DbException) SQLException(java.sql.SQLException) IOException(java.io.IOException) EOFException(java.io.EOFException) ResultSetMetaData(java.sql.ResultSetMetaData) JdbcStatement(org.h2.jdbc.JdbcStatement) ByteArrayInputStream(java.io.ByteArrayInputStream) ResultSet(java.sql.ResultSet) JdbcResultSet(org.h2.jdbc.JdbcResultSet) StringReader(java.io.StringReader) ConnectionInfo(org.h2.engine.ConnectionInfo) JdbcPreparedStatement(org.h2.jdbc.JdbcPreparedStatement) ParameterMetaData(java.sql.ParameterMetaData) ScriptReader(org.h2.util.ScriptReader)

Aggregations

DbException (org.h2.message.DbException)10 ConnectionInfo (org.h2.engine.ConnectionInfo)9 Properties (java.util.Properties)8 IOException (java.io.IOException)5 SQLException (java.sql.SQLException)5 Database (org.h2.engine.Database)4 Session (org.h2.engine.Session)4 SysProperties (org.h2.engine.SysProperties)4 ConnectionInfo (org.h2.server.web.ConnectionInfo)3 SortedProperties (org.h2.util.SortedProperties)3 File (java.io.File)2 Field (java.lang.reflect.Field)2 InvocationTargetException (java.lang.reflect.InvocationTargetException)2 Method (java.lang.reflect.Method)2 Socket (java.net.Socket)2 JdbcConnection (org.h2.jdbc.JdbcConnection)2 Transfer (org.h2.value.Transfer)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 DataInputStream (java.io.DataInputStream)1 EOFException (java.io.EOFException)1