public function generate(DataSourceHandler $handler, DatasetMetaData $dataset) {
        $assembledTableName = assemble_database_entity_name($handler, $dataset->datasourceName, $dataset->source);

        // NOTE: we cannot use TRUNCATE TABLE because this operation has to be part of a transaction
        // Also truncate does to work in some databases when there are FOREIGN KEYs pointing to this table
        return "DELETE FROM $assembledTableName";
    }
    public function prepare(DataSourceHandler $handler, DataSourceMetaData $datasource, $tableName, array $columnNames, array $records) {
        $sqls = NULL;

        $assembledTableName = assemble_database_entity_name($handler, $datasource->name, $tableName);

        $header = "INSERT INTO $assembledTableName (" . implode(', ', $columnNames) . ') VALUES ';

        foreach ($records as $record) {
            $sqls[] = $header . '(' . implode(', ', $record) . ')';
        }

        return $sqls;
    }
    public function prepare(DataSourceHandler $handler, DataSourceMetaData $datasource, $tableName, array $columnNames, array $records) {
        $sql = NULL;

        $assembledTableName = assemble_database_entity_name($handler, $datasource->name, $tableName);

        $header = "INTO $assembledTableName (" . implode(', ', $columnNames) . ') VALUES';

        foreach ($records as $record) {
            $sql .= "\n  $header (" . implode(', ', $record) . ')';
        }

        $sql = "INSERT ALL$sql\nSELECT * FROM dual";

        return $sql;
    }
    public function prepare(DataSourceHandler $handler, DataSourceMetaData $datasource, $tableName, array $setColumnValues = NULL, array $whereColumnValues = NULL) {
        // we do not need to update any columns. Just ignoring this request
        if (!isset($setColumnValues)) {
            return NULL;
        }

        $assembledTableName = assemble_database_entity_name($handler, $datasource->name, $tableName);

        $sql = "UPDATE $assembledTableName SET " . $this->prepareColumnExpressions($setColumnValues, ', ');
        if (isset($whereColumnValues)) {
            $sql .= ' WHERE ' . $this->prepareColumnExpressions($whereColumnValues, ' AND ');
        }

        return $sql;
    }
    public function prepare(DataSourceHandler $handler, DataSourceMetaData $datasource, $tableName, array $columnNames, array $records) {
        $indent = str_pad('', InsertStatementPrint::INDENT__VALUES);

        $assembledTableName = assemble_database_entity_name($handler, $datasource->name, $tableName);

        $sql = NULL;
        foreach ($records as $record) {
            if (isset($sql)) {
                $sql .= ",\n{$indent}       ";
            }

            $sql .= '(' . implode(', ', $record) . ')';
        }

        $sql = "INSERT INTO $assembledTableName (" . implode(', ', $columnNames) . ")\n{$indent}VALUES " . $sql;

        return $sql;
    }
    public function prepare(DataSourceHandler $handler, DataSourceMetaData $datasource, $tableName, array $keys = NULL) {
        $sqls = NULL;

        $assembledTableName = assemble_database_entity_name($handler, $datasource->name, $tableName);

        if (isset($keys)) {
            $header = "DELETE FROM $assembledTableName";

            foreach ($keys as $key) {
                $s = NULL;

                foreach ($key as $columnName => $value) {
                    if (isset($s)) {
                        $s .= ' AND ';
                    }
                    else {
                        $s = ' WHERE ';
                    }

                    $s .=  $columnName;

                    if (is_array($value)) {
                        if (count($value) == 1) {
                            $s .= ' = ' . $value[0];
                        }
                        else {
                            $s .= ' IN (' . implode(', ', $value) . ')';
                        }
                    }
                    else {
                        $s .= ' = ' . $value;
                    }
                }

                $sqls[] = $header . $s;
            }
        }

        return $sqls;
    }
    public function generate(DataSourceHandler $handler, DatasetMetaData $dataset) {
        $assembledTableName = assemble_database_entity_name($handler, $dataset->datasourceName, $dataset->source);

        return "DROP TABLE $assembledTableName";
    }
    public function prepareTableUpdateStatement(DataSourceHandler $handler, DataControllerCallContext $callcontext, DatasetMetaData $dataset, array $operations) {
        $assembledTableName = assemble_database_entity_name($handler, $dataset->datasourceName, $dataset->source);

        $indent = str_pad('', SelectStatementPrint::INDENT);

        $sql = '';
        foreach ($operations as $operation) {
            if ($sql != '') {
                $sql .= $this->getUpdateClauseDelimiter();
            }
            $this->prepareTableUpdateOperation($handler, $callcontext, $dataset, $operation, $indent, $sql);
        }

        return ($sql == '') ? NULL : "ALTER TABLE $assembledTableName{$sql}";
    }
    protected function assembleTableName() {
        $assembledTableName = $this->name;

        $index = strpos($assembledTableName, '.');
        if ($index === FALSE) {
            $environment_metamodel = data_controller_get_environment_metamodel();

            $datasourceName = $this->dataset->datasourceName;
            $datasource = $environment_metamodel->getDataSource($datasourceName);

            $datasourceQueryHandler = DataSourceQueryFactory::getInstance()->getHandler($datasource->type);

            $assembledTableName = assemble_database_entity_name($datasourceQueryHandler, $datasource->name, $assembledTableName);
        }

        return $assembledTableName;
    }