private PreparedStatement internalPrepareStatement ( final String sql , final int resultSetScrollType , final int resultSetConcurrency , final int autoGeneratedKeys ) throws SQLException { if ( sql != null ) { String sqlQuery = Utils . nativeSql ( sql , protocol . noBackslashEscapes ( ) ) ; if ( options . useServerPrepStmts && PREPARABLE_STATEMENT_PATTERN . matcher ( sqlQuery ) . find ( ) ) { //prepare isn't delayed -> if prepare fail, fallback to client preparedStatement? checkConnection ( ) ; try { return new ServerSidePreparedStatement ( this , sqlQuery , resultSetScrollType , resultSetConcurrency , autoGeneratedKeys ) ; } catch ( SQLNonTransientConnectionException e ) { throw e ; } catch ( SQLException e ) { //on some specific case, server cannot prepared data (CONJ-238) //will use clientPreparedStatement } } return new ClientSidePreparedStatement ( this , sqlQuery , resultSetScrollType , resultSetConcurrency , autoGeneratedKeys ) ; } else { throw new SQLException ( "SQL value can not be NULL" ) ; } }
Send ServerPrepareStatement or ClientPrepareStatement depending on SQL query and options If server side and PREPARE can be delayed a facade will be return to have a fallback on client prepareStatement .