package com.tesora.dve.sql.util;
/*
* #%L
* Tesora Inc.
* Database Virtualization Engine
* %%
* Copyright (C) 2011 - 2014 Tesora Inc.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
import com.tesora.dve.concurrent.SynchronousListener;
import io.netty.channel.EventLoopGroup;
import io.netty.util.CharsetUtil;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import com.tesora.dve.common.DBHelper;
import com.tesora.dve.common.PEConstants;
import com.tesora.dve.common.PEUrl;
import com.tesora.dve.common.UserVisibleDatabase;
import com.tesora.dve.common.catalog.CatalogDAO;
import com.tesora.dve.common.catalog.PersistentSite;
import com.tesora.dve.common.catalog.StorageSite;
import com.tesora.dve.common.catalog.TestCatalogHelper;
import com.tesora.dve.concurrent.PEDefaultPromise;
import com.tesora.dve.db.GenericSQLCommand;
import com.tesora.dve.db.mysql.MysqlConnection;
import com.tesora.dve.db.mysql.MysqlPrepareStatementCollector;
import com.tesora.dve.db.mysql.MysqlMessage;
import com.tesora.dve.db.mysql.MysqlStmtCloseCommand;
import com.tesora.dve.db.mysql.libmy.MyPreparedStatement;
import com.tesora.dve.db.mysql.portal.protocol.ClientCapabilities;
import com.tesora.dve.db.mysql.portal.protocol.MSPComStmtCloseRequestMessage;
import com.tesora.dve.db.mysql.portal.protocol.MysqlGroupedPreparedStatementId;
import com.tesora.dve.exceptions.PEException;
import com.tesora.dve.server.messaging.SQLCommand;
import com.tesora.dve.server.statistics.manager.LogSiteStatisticRequest;
import com.tesora.dve.sql.parser.ParserInvoker.LineInfo;
import com.tesora.dve.standalone.PETest;
import com.tesora.dve.worker.AdditionalConnectionInfo;
import com.tesora.dve.worker.MysqlPreparedStmtExecuteCollector;
import com.tesora.dve.worker.MysqlTextResultChunkProvider;
import com.tesora.dve.worker.UserAuthentication;
import com.tesora.dve.worker.Worker;
public class MysqlConnectionResource extends ConnectionResource {
private String url;
private String userName;
private String password;
private boolean connected = false;
private final boolean useUTF8;
private Charset encoding;
private MysqlConnection mysqlConn;
public MysqlConnectionResource() throws Throwable {
this(true);
}
public MysqlConnectionResource(final boolean useUTF8) throws Throwable {
super(null);
this.useUTF8 = useUTF8;
Properties catalogProps = TestCatalogHelper.getTestCatalogProps(PETest.class);
String portalPort = catalogProps.getProperty(PEConstants.MYSQL_PORTAL_PORT_PROPERTY, PEConstants.MYSQL_PORTAL_DEFAULT_PORT);
PEUrl peurl = PEUrl.fromUrlString(catalogProps.getProperty(DBHelper.CONN_URL));
peurl.setQueryOptions(new Properties());
peurl.setPort(portalPort);
init(peurl.getURL(), catalogProps.getProperty(DBHelper.CONN_USER), catalogProps.getProperty(DBHelper.CONN_PASSWORD), useUTF8);
}
private MysqlConnectionResource(String url, String userName, String password, final boolean useUTF8) throws Throwable {
super(null);
this.useUTF8 = useUTF8;
init(url, userName, password, useUTF8);
}
private void init(String url, String userName, String password, boolean useUTF8) throws Throwable {
this.url = url;
this.userName = userName;
this.password = password;
if (useUTF8) {
this.encoding = CharsetUtil.UTF_8;
addPostConnectCmd("SET NAMES utf8");
} else {
this.encoding = CharsetUtil.ISO_8859_1;
addPostConnectCmd("SET NAMES latin1");
}
mysqlConn = new MysqlConnection(new TestStorageSite());
connect();
}
@Override
public ResourceResponse execute(LineInfo info, String stmt) throws Throwable {
return execute(new SQLCommand(this.encoding, stmt));
}
public ResourceResponse execute(LineInfo info, Charset encoding, byte[] stmt) throws Throwable {
return execute(new SQLCommand(new GenericSQLCommand(encoding, stmt)));
}
private ResourceResponse execute(SQLCommand sqlc) throws Throwable {
MysqlTextResultChunkProvider results = new MysqlTextResultChunkProvider();
PEDefaultPromise<Boolean> promise = new PEDefaultPromise<Boolean>();
results.getDispatchBundle(mysqlConn, sqlc, promise).writeAndFlush(mysqlConn);
SynchronousListener.sync(promise);
return new ProxyConnectionResourceResponse(results);
}
@Override
public Object prepare(LineInfo info, String stmt) throws Throwable {
MysqlPrepareStatementCollector collector = new MysqlPrepareStatementCollector();
PEDefaultPromise<Boolean> promise = new PEDefaultPromise<Boolean>();
collector.getDispatchBundle(mysqlConn, new SQLCommand(this.encoding, stmt), promise).writeAndFlush(mysqlConn);;
SynchronousListener.sync(promise);
return collector.getPreparedStatement();
}
@Override
public ResourceResponse executePrepared(Object id, List<Object> parameters)
throws Throwable {
@SuppressWarnings("unchecked")
MyPreparedStatement<MysqlGroupedPreparedStatementId> pstmt = (MyPreparedStatement<MysqlGroupedPreparedStatementId>) id;
MysqlPreparedStmtExecuteCollector collector = new MysqlPreparedStmtExecuteCollector(pstmt);
SQLCommand sqlc = new SQLCommand(new GenericSQLCommand(this.encoding, "EXEC PREPARED"), parameters);
PEDefaultPromise<Boolean> promise = new PEDefaultPromise<Boolean>();
collector.getDispatchBundle(mysqlConn, sqlc, promise).writeAndFlush(mysqlConn);
SynchronousListener.sync(promise);
return new ProxyConnectionResourceResponse(collector);
}
@Override
public void destroyPrepared(Object id) throws Throwable {
@SuppressWarnings("unchecked")
MyPreparedStatement<MysqlGroupedPreparedStatementId> pstmt = (MyPreparedStatement<MysqlGroupedPreparedStatementId>) id;
int preparedID = (int)pstmt.getStmtId().getStmtId(mysqlConn.getPhysicalID());
MysqlMessage message = MSPComStmtCloseRequestMessage.newMessage(preparedID);
mysqlConn.writeAndFlush(message, new MysqlStmtCloseCommand(preparedID, new PEDefaultPromise<Boolean>()));
}
@Override
public ResourceResponse fetch(LineInfo info, String stmt) throws Throwable {
return execute(info, stmt);
}
@Override
public void connect() throws Throwable {
mysqlConn.connect(url, userName, password, ClientCapabilities.DEFAULT_PSITE_CAPABILITIES);
connected = true;
executePostConnectCmds();
}
@Override
public void disconnect() throws Throwable {
mysqlConn.close();
mysqlConn = null;
connected = false;
}
public MysqlConnection getConnection() {
return mysqlConn;
}
@Override
public boolean isConnected() throws Throwable {
return connected;
}
@Override
public String describe() {
return mysqlConn.toString();
}
@Override
public ConnectionResource getNewConnection() throws Throwable {
return new MysqlConnectionResource(this.url, this.userName, this.password, this.useUTF8);
}
@Override
public ExceptionClassification classifyException(Throwable t) {
return null;
}
class TestStorageSite implements StorageSite {
@Override
public String getName() {
return null;
}
@Override
public String getMasterUrl() {
return null;
}
@Override
public String getInstanceIdentifier() {
return null;
}
@Override
public PersistentSite getRecoverableSite(CatalogDAO c) {
return null;
}
@Override
public Worker pickWorker(Map<StorageSite, Worker> workerMap)
throws PEException {
return null;
}
@Override
public void annotateStatistics(LogSiteStatisticRequest sNotice) {
}
@Override
public void incrementUsageCount() {
}
@Override
public Worker createWorker(UserAuthentication auth, AdditionalConnectionInfo additionalConnInfo, EventLoopGroup preferredEventLoop) throws PEException {
return null;
}
@Override
public void onSiteFailure(CatalogDAO c) throws PEException {
}
@Override
public int getMasterInstanceId() {
return 0;
}
@Override
public boolean supportsTransactions() {
return false;
}
@Override
public boolean hasDatabase(UserVisibleDatabase ctxDB) {
return false;
}
@Override
public void setHasDatabase(UserVisibleDatabase ctxDB) {
// TODO Auto-generated method stub
}
}
}