/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.wasp.jdbc.command;
import com.alibaba.wasp.ReadModel;
import com.alibaba.wasp.SQLErrorCode;
import com.alibaba.wasp.client.FClient;
import com.alibaba.wasp.jdbc.JdbcException;
import com.alibaba.wasp.jdbc.expression.ParameterInterface;
import com.alibaba.wasp.jdbc.result.ResultInterface;
import com.alibaba.wasp.jdbc.result.ResultRemote;
import com.alibaba.wasp.jdbc.result.ResultTransfer;
import com.alibaba.wasp.jdbc.value.Value;
import com.alibaba.wasp.jdbc.value.ValueInt;
import com.alibaba.wasp.meta.Field;
import com.alibaba.wasp.session.ConnectionSession;
import com.alibaba.wasp.session.ExecuteSession;
import com.alibaba.wasp.session.SessionFactory;
import com.alibaba.wasp.util.New;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* Represents the client-side part of a SQL statement. This class is not used in
* embedded mode.
*/
public class CommandRemote implements CommandInterface {
private Log log = LogFactory.getLog(CommandRemote.class);
private final ArrayList<ParameterInterface> parameters;
private final String sql;
private final int fetchSize;
private ConnectionSession session;
private final FClient fClient;
private int id;
private boolean isQuery;
private final int created;
private final ReadModel readModel;
private final boolean autoCommit;
private ExecuteSession statementSession;
private final List<String> sqls;
public CommandRemote(FClient fClient, ConnectionSession session, String sql,
int fetchSize, ReadModel readModel, boolean autoCommit, ExecuteSession statementSession, List<String> sqls) {
this.sql = sql;
parameters = New.arrayList();
prepare(session, true);
// set session late because prepare might fail - in this case we don't
// need to close the object
this.session = session;
this.fClient = fClient;
this.fetchSize = fetchSize;
this.readModel = readModel;
this.autoCommit = autoCommit;
this.statementSession = statementSession;
this.sqls = sqls;
created = session.getLastReconnect();
}
public CommandRemote(FClient fClient, ConnectionSession session, List<String> sqls,
boolean autoCommit, ExecuteSession statementSession) {
this(fClient, session, null, 0, null, autoCommit, statementSession, sqls);
}
private void prepare(ConnectionSession s, boolean createParams) {
if (fetchSize > 0) {
isQuery = true;
}
}
@Override
public boolean isQuery() {
return isQuery;
}
@Override
public ArrayList<ParameterInterface> getParameters() {
return parameters;
}
private void prepareIfRequired() {
if (session.getLastReconnect() != created) {
// in this case we need to prepare again in every case
id = Integer.MIN_VALUE;
}
session.checkClosed();
if (id <= session.getCurrentId()) {
// object is too old - we need to prepare again
prepare(session, false);
}
}
@Override
public ResultInterface getMetaData() {
return null;
}
@Override
public ResultInterface executeQuery(int maxRows) throws SQLException {
checkParameters();
synchronized (session) {
int objectId = session.getNextId();
ResultRemote result = null;
prepareIfRequired();
try {
ResultTransfer transfer = new ResultTransfer(null, null);
result = new ResultRemote(fClient, SessionFactory.createExecuteSession(), transfer, sql, objectId,
fetchSize, true, readModel, false, null);
isQuery = result.isQuery();
if (!isQuery() && result.getRowCount() > 0) {
throw JdbcException.get(SQLErrorCode.METHOD_ONLY_ALLOWED_FOR_QUERY,
"sql:" + sql);
}
} catch (IOException e) {
session.removeServer(e);
}
return result;
}
}
private String getTableName(String sql) {
return null; // To change body of created methods use File | Settings | File
// Templates.
}
private List<Field> getFileds(String sql) {
return null; // To change body of created methods use File | Settings | File
// Templates.
}
@Override
public int executeUpdate() throws SQLException {
checkParameters();
synchronized (session) {
prepareIfRequired();
ResultRemote result = null;
String tablename = getTableName(sql);
ResultTransfer transfer = new ResultTransfer(null, tablename);
try {
result = new ResultRemote(fClient, statementSession, transfer, sql, readModel);
result.next();
isQuery = result.isQuery();
if (isQuery()) {
throw JdbcException.get(SQLErrorCode.METHOD_NOT_ALLOWED_FOR_QUERY,
"sql:" + sql);
}
Value[] values = result.currentRow();
if (values == null || values.length == 0) {
return 0;
}
if (values[0] instanceof ValueInt) {
return ((ValueInt) values[0]).getInt();
}
} catch (IOException e) {
session.removeServer(e);
}
return transfer.getCounts();
}
}
@Override
public int executeTransaction() throws SQLException {
checkParameters();
synchronized (session) {
prepareIfRequired();
ResultRemote result = null;
ResultTransfer transfer = new ResultTransfer(null, null);
try {
result = new ResultRemote(fClient, statementSession, transfer, sqls, true);
result.next();
isQuery = result.isQuery();
if (isQuery()) {
throw JdbcException.get(SQLErrorCode.METHOD_NOT_ALLOWED_FOR_QUERY,
"sql:" + sql);
}
Value[] values = result.currentRow();
if (values == null || values.length == 0) {
return 0;
}
if (values[0] instanceof ValueInt) {
return ((ValueInt) values[0]).getInt();
}
} catch (IOException e) {
session.removeServer(e);
}
return transfer.getCounts();
}
}
private void checkParameters() {
for (ParameterInterface p : parameters) {
p.checkSet();
}
}
@Override
public void close() {
if (session == null || session.isClosed()) {
return;
}
session = null;
try {
for (ParameterInterface p : parameters) {
Value v = p.getParamValue();
if (v != null) {
v.close();
}
}
} catch (JdbcException e) {
log.error("close", e);
}
parameters.clear();
}
/**
* Cancel this current statement.
*/
@Override
public void cancel() {
session.cancelStatement(id);
}
@Override
public String toString() {
return sql;
}
@Override
public int getCommandType() {
return UNKNOWN;
}
}