/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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/>.
*/
package com.foundationdb.sql.pg;
import com.foundationdb.server.api.DDLFunctions;
import com.foundationdb.server.service.monitor.SessionMonitor.StatementTypes;
import com.foundationdb.server.service.session.Session;
import com.foundationdb.sql.aisddl.AISDDL;
import com.foundationdb.sql.aisddl.TableDDL;
import com.foundationdb.sql.parser.*;
import com.foundationdb.qp.operator.QueryBindings;
import com.foundationdb.sql.types.DataTypeDescriptor;
import com.foundationdb.util.tap.InOutTap;
import com.foundationdb.util.tap.Tap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static com.foundationdb.server.service.dxl.DXLFunctionsHook.DXLFunction;
/** SQL DDL statements. */
public class PostgresDDLStatement extends PostgresBaseStatement
{
private static final Logger logger = LoggerFactory.getLogger(PostgresDDLStatement.class);
private static final InOutTap EXECUTE_TAP = Tap.createTimer("PostgresDDLStatement: execute shared");
private DDLStatementNode ddl;
private String sql;
private List<String> columnNames = null;
private List<PostgresType> columnTypes = null;
PostgresOperatorStatement opstmt;
public PostgresDDLStatement(DDLStatementNode ddl, String sql) {
this.sql = sql;
this.ddl = ddl;
}
public PostgresDDLStatement(DDLStatementNode ddl, String sql, PostgresOperatorStatement opstmt) {
this.sql = sql;
this.ddl = ddl;
this.opstmt = opstmt;
}
@Override
public PostgresStatement finishGenerating(PostgresServerSession server,
String sql, StatementNode stmt,
List<ParameterNode> params, int[] paramTypes) {
if(opstmt != null) {
opstmt.finishGenerating(server, sql, ((CreateTableNode) stmt).getQueryExpression(), params, paramTypes);
columnNames = opstmt.getColumnNames();
columnTypes = opstmt.getColumnTypes();
}
super.finishGenerating(server,sql, stmt, params, paramTypes);
return this;
}
@Override
public PostgresType[] getParameterTypes() {
return null;
}
@Override
public void sendDescription(PostgresQueryContext context,
boolean always, boolean params)
throws IOException {
if (always) {
PostgresServerSession server = context.getServer();
PostgresMessenger messenger = server.getMessenger();
if (params) {
messenger.beginMessage(PostgresMessages.PARAMETER_DESCRIPTION_TYPE.code());
messenger.writeShort(0);
messenger.sendMessage();
}
messenger.beginMessage(PostgresMessages.NO_DATA_TYPE.code());
messenger.sendMessage();
}
}
@Override
public TransactionMode getTransactionMode() {
if(opstmt != null){
return TransactionMode.IMPLICIT_COMMIT_AND_NEW;
}
return TransactionMode.IMPLICIT_COMMIT;
}
@Override
public TransactionAbortedMode getTransactionAbortedMode() {
return TransactionAbortedMode.NOT_ALLOWED;
}
@Override
public AISGenerationMode getAISGenerationMode() {
return AISGenerationMode.ALLOWED;
}
@Override
public boolean putInCache() {
return false;
}
@Override
public PostgresStatementResult execute(PostgresQueryContext context, QueryBindings bindings, int maxrows) throws IOException {
PostgresServerSession server = context.getServer();
server.getSessionMonitor().countEvent(StatementTypes.DDL_STMT);
PostgresMessenger messenger = server.getMessenger();
//if this is a create table node with a query expression use special case
if(ddl.getNodeType() == NodeTypes.CREATE_TABLE_NODE && ((CreateTableNode)ddl).getQueryExpression() != null){
try{
preExecute(context, DXLFunction.UNSPECIFIED_DDL_WRITE);
String schema = server.getDefaultSchemaName();
DDLFunctions ddlFunctions = server.getDXL().ddlFunctions();
Session session = server.getSession();
List<DataTypeDescriptor> descriptors = new ArrayList<>();
for(PostgresType columnType: columnTypes){
descriptors.add(columnType.getType().dataTypeDescriptor());
}
TableDDL.createTable(ddlFunctions, session, schema, (CreateTableNode) ddl, context, descriptors, columnNames, server);
}
finally {
postExecute(context, DXLFunction.UNSPECIFIED_DDL_WRITE);
}
} else {
try {
preExecute(context, DXLFunction.UNSPECIFIED_DDL_WRITE);
AISDDL.execute(ddl, sql, context);
} finally {
postExecute(context, DXLFunction.UNSPECIFIED_DDL_WRITE);
}
}
return statementComplete(ddl);
}
@Override
protected InOutTap executeTap()
{
return EXECUTE_TAP;
}
}