Open TomasAlcalde opened 3 months ago
tu clase debería tener un atributo RecordRef out
. Esta clase no tiene valores sino punteros a valores, por lo que puedes crear un valor representante de null en alguna parte (ojo que no se destruya antes de tiempo, por ejemplo puedes tenerlo como atributo de clase) y apuntar a él cuando sea necesario.
Por ejemplo, si la columna i
es la que quieres asignar null, puedes hacer out.values[i] = &my_null_value;
, pero ojo que cuando deje de ser null debes reasignar para que apunte al lugar original.
Muchas gracias, aunque tengo la duda de como hacer para que no se destruya antes de tiempo.
Actualmente, lo declaré como un atributo de clase de los iteradores, de la siguiente manera:
Value int_null_value = Value(-1);
Value str_null_value = Value("-1");
Entonces dependiendo del datatype de la columna hago:
out.values[offset + i] = &int_null_value;
Sin embargo, al imprimir la tabla no aparecen los cambios a -1.
Tampoco me queda claro la última parte de que cuando deje de ser null debo reasignar para que apunte al lugar original.
con lugar original me refiero al que se setea en el constructor, por ejemplo en el join sería esto:
for (size_t i = 0; i < projected_lhs_columns_pos.size(); i++) {
out.values[i] = lhs_out.values[projected_lhs_columns_pos[i]];
}
size_t offset = projected_lhs_columns_pos.size();
for (size_t i = 0; i < projected_rhs_columns_pos.size(); i++) {
out.values[offset + i] = rhs_out.values[projected_rhs_columns_pos[i]];
}
Gracias.
Aun quedé con la duda de como implementar los punteros a valores nulos. Los cree como atributo de clase, pero al imprimir el resultado estos quedan como la última tupla de rhs.
Disculpa, lo que dije estaba mal, creo que van a tener que manejar una copia del record, y sobreescribir este cada vez que se actualice rhs o lhs, y en esa copia van a tener que setear el nulo cuando corresponda. Voy a pensarlo un poco más y trataré de dejar un ejemplo.
acá dejo un ejemplo del operador join, pero que ahora out apunta a una copia de los valores en vez de apuntar directamente a los valores de los hijos.
#pragma once
#include "query/executor/query_iter.h"
class Join : public QueryIter {
public:
// helper function for construction of lhs_record_copy and rhs_record_copy
static std::vector<DataType> get_datatypes(const std::vector<Column>& columns) {
std::vector<DataType> res;
for (auto& column : columns) {
res.push_back(column.datatype);
}
return res;
}
Join(
std::unique_ptr<QueryIter> _lhs,
std::unique_ptr<QueryIter> _rhs,
std::vector<Column> _projected_lhs_columns,
std::vector<Column> _projected_rhs_columns,
std::vector<size_t> _projected_lhs_columns_pos,
std::vector<size_t> _projected_rhs_columns_pos,
std::vector<std::pair<size_t, size_t>> _equalities
) :
lhs (std::move(_lhs)),
rhs (std::move(_rhs)),
projected_lhs_columns (std::move(_projected_lhs_columns)),
projected_rhs_columns (std::move(_projected_rhs_columns)),
projected_lhs_columns_pos (std::move(_projected_lhs_columns_pos)),
projected_rhs_columns_pos (std::move(_projected_rhs_columns_pos)),
equalities (std::move(_equalities)),
lhs_out (lhs->get_output()),
rhs_out (rhs->get_output()),
out (projected_lhs_columns.size() + projected_rhs_columns.size()),
lhs_record_copy (get_datatypes(lhs->get_columns())),
rhs_record_copy (get_datatypes(rhs->get_columns()))
{
assert(equalities.size() > 0);
assert(projected_lhs_columns.size() == projected_lhs_columns_pos.size());
assert(projected_rhs_columns.size() == projected_rhs_columns_pos.size());
for (size_t i = 0; i < projected_lhs_columns_pos.size(); i++) {
out.values[i] = &lhs_record_copy.values[projected_lhs_columns_pos[i]];
}
size_t offset = projected_lhs_columns_pos.size();
for (size_t i = 0; i < projected_rhs_columns_pos.size(); i++) {
out.values[offset + i] = &rhs_record_copy.values[projected_rhs_columns_pos[i]];
}
}
void begin() override {
lhs->begin();
rhs->begin();
valid_lhs = false;
}
// simple nested loop join
bool next() override {
while (true) {
if (valid_lhs) {
while (rhs->next()) {
// copy rhs new values
for (size_t i = 0; i < rhs_record_copy.values.size(); i++) {
rhs_record_copy.values[i] = *rhs_out.values[i];
}
// if compatible return true, else continue
bool compatible = true;
for (auto& eq: equalities) {
if (*lhs_out.values[eq.first] != *rhs_out.values[eq.second]) {
compatible = false;
break;
}
}
if (compatible) return true;
}
valid_lhs = false;
} else {
if (lhs->next()) {
// copy lhs new values
for (size_t i = 0; i < lhs_record_copy.values.size(); i++) {
lhs_record_copy.values[i] = *lhs_out.values[i];
}
valid_lhs = true;
rhs->reset();
} else {
return false;
}
}
}
return false;
}
void reset() override {
lhs->reset();
rhs->reset();
}
RecordRef& get_output() override {
return out;
}
std::vector<Column> get_columns() override {
std::vector<Column> res = projected_lhs_columns;
for (auto& c : projected_rhs_columns) {
res.push_back(c);
}
return res;
}
std::ostream& print_to_ostream(std::ostream& os, int indent = 0) const override {
os << std::string(indent, ' ');
os << "Join(";
os << projected_lhs_columns[equalities[0].first].alias << "." << projected_lhs_columns[equalities[0].first].column;
os << " == ";
os << projected_rhs_columns[equalities[0].second].alias << "." << projected_rhs_columns[equalities[0].second].column;
for (size_t i = 1; i < equalities.size(); ++i) {
os << " AND ";
os << projected_lhs_columns[equalities[1].first].alias << "." << projected_lhs_columns[equalities[1].first].column;
os << " == ";
os << projected_rhs_columns[equalities[1].second].alias << "." << projected_rhs_columns[equalities[1].second].column;
}
os << ")\n";
lhs->print_to_ostream(os, indent + 2);
rhs->print_to_ostream(os, indent + 2);
return os;
}
private:
std::unique_ptr<QueryIter> lhs;
std::unique_ptr<QueryIter> rhs;
std::vector<Column> projected_lhs_columns;
std::vector<Column> projected_rhs_columns;
std::vector<size_t> projected_lhs_columns_pos;
std::vector<size_t> projected_rhs_columns_pos;
std::vector<std::pair<size_t, size_t>> equalities;
RecordRef& lhs_out;
RecordRef& rhs_out;
RecordRef out;
Record lhs_record_copy;
Record rhs_record_copy;
bool valid_lhs;
};
En este caso puedes asignar un nulo modificando la copia, ej:
lhs_record_copy.values[projected_lhs_columns_pos[i]] = Value(-1);
Hola, Logré implementar la lógica del left outer join y devuelve las tuplas buscadas. Sin embargo, las tuplas del lado izquierdo que no coinciden con ninguna del lado derecho las estoy retornando con los valores de la última tupla del lado derecho. No entiendo muy bien como sobreescribir los valores con -1. Muchas gracias