////////////////////////////////////////////////////////////////////////// // // pgScript - PostgreSQL Tools // // Copyright (C) 2002 - 2016, The pgAdmin Development Team // This software is released under the PostgreSQL Licence // ////////////////////////////////////////////////////////////////////////// #include "pgAdmin3.h" #include "pgscript/objects/pgsString.h" #include #include "pgscript/objects/pgsNumber.h" #include "pgscript/objects/pgsRecord.h" #include "pgscript/exceptions/pgsArithmeticException.h" #include "pgscript/exceptions/pgsCastException.h" pgsString::pgsString(const wxString &data) : pgsVariable(pgsVariable::pgsTString), m_data(data) { } pgsString::~pgsString() { } pgsVariable *pgsString::clone() const { return pnew pgsString(*this); } wxString pgsString::value() const { return m_data; } pgsOperand pgsString::eval(pgsVarMap &vars) const { return this->clone(); } pgsOperand pgsString::pgs_plus(const pgsVariable &rhs) const { if (rhs.is_string()) { return pnew pgsString(m_data + rhs.value()); } else { throw pgsArithmeticException(m_data, rhs.value()); } } pgsOperand pgsString::pgs_minus(const pgsVariable &rhs) const { throw pgsArithmeticException(m_data, rhs.value()); } pgsOperand pgsString::pgs_times(const pgsVariable &rhs) const { throw pgsArithmeticException(m_data, rhs.value()); } pgsOperand pgsString::pgs_over(const pgsVariable &rhs) const { throw pgsArithmeticException(m_data, rhs.value()); } pgsOperand pgsString::pgs_modulo(const pgsVariable &rhs) const { throw pgsArithmeticException(m_data, rhs.value()); } pgsOperand pgsString::pgs_equal(const pgsVariable &rhs) const { if (rhs.is_string()) { return pnew pgsNumber(m_data == rhs.value() ? wxT("1") : wxT("0")); } else { throw pgsArithmeticException(m_data, rhs.value()); } } pgsOperand pgsString::pgs_different(const pgsVariable &rhs) const { if (rhs.is_string()) { return pnew pgsNumber(m_data != rhs.value() ? wxT("1") : wxT("0")); } else { throw pgsArithmeticException(m_data, rhs.value()); } } pgsOperand pgsString::pgs_greater(const pgsVariable &rhs) const { if (rhs.is_string()) { return pnew pgsNumber(m_data > rhs.value() ? wxT("1") : wxT("0")); } else { throw pgsArithmeticException(m_data, rhs.value()); } } pgsOperand pgsString::pgs_lower(const pgsVariable &rhs) const { if (rhs.is_string()) { return pnew pgsNumber(m_data < rhs.value() ? wxT("1") : wxT("0")); } else { throw pgsArithmeticException(m_data, rhs.value()); } } pgsOperand pgsString::pgs_lower_equal(const pgsVariable &rhs) const { if (rhs.is_string()) { return pnew pgsNumber(m_data <= rhs.value() ? wxT("1") : wxT("0")); } else { throw pgsArithmeticException(m_data, rhs.value()); } } pgsOperand pgsString::pgs_greater_equal(const pgsVariable &rhs) const { if (rhs.is_string()) { return pnew pgsNumber(m_data >= rhs.value() ? wxT("1") : wxT("0")); } else { throw pgsArithmeticException(m_data, rhs.value()); } } pgsOperand pgsString::pgs_not() const { wxString data = m_data.Strip(wxString::both); return pnew pgsString(data.IsEmpty() ? wxT("1") : wxT("")); } bool pgsString::pgs_is_true() const { wxString data = m_data.Strip(wxString::both); return (!data.IsEmpty() ? true : false); } pgsOperand pgsString::pgs_almost_equal(const pgsVariable &rhs) const { if (rhs.is_string()) { return pnew pgsNumber(m_data.CmpNoCase(rhs.value()) == 0 ? wxT("1") : wxT("0")); } else { throw pgsArithmeticException(m_data, rhs.value()); } } pgsNumber pgsString::number() const { wxString data = m_data.Strip(wxString::both); pgsTypes type = pgsNumber::num_type(data); switch (type) { case pgsTInt: return pgsNumber(data, pgsInt); case pgsTReal: return pgsNumber(data, pgsReal); default: throw pgsCastException(data, wxT("number")); } } pgsRecord pgsString::record() const { pgsRecord *rec = 0; // Try to find the representation of a record in the string { wxString element(wxT("(\"([^\"\\\\]|\\\\.)*\")|((-|[a-zA-Z0-9\\+\\.])+)")); wxString data(m_data); wxRegEx regex1(wxString() << wxT("^[[:space:]]*\\([[:space:]]*(") << element << wxT(")[[:space:]]*([,][[:space:]]*(") << element << wxT(")[[:space:]]*)*\\)"), wxRE_DEFAULT | wxRE_ICASE); // Find each line size_t line_nb = 0, nb_of_columns = 0; bool count_columns = true; while (regex1.Matches(data)) { // Process that line: find each element wxString line(regex1.GetMatch(data)); wxRegEx regex2(element); size_t column_nb = 0; while (regex2.Matches(line)) { if (count_columns == true) { ++nb_of_columns; } else { if (column_nb < nb_of_columns && rec != 0) { wxString value(regex2.GetMatch(line)); if (value.StartsWith(wxT("\"")) && value.EndsWith(wxT("\""))) { // This is a string value = value.Mid(1, value.Len() - 2); value.Replace(wxT("\\\""), wxT("\"")); value.Replace(wxT("\\\\"), wxT("\\")); rec->insert(line_nb, column_nb, pnew pgsString(value)); } else { // This is a number or a string pgsTypes type = pgsNumber::num_type(value); switch (type) { case pgsTInt: rec->insert(line_nb, column_nb, pnew pgsNumber(value, pgsInt)); break; case pgsTReal: rec->insert(line_nb, column_nb, pnew pgsNumber(value, pgsReal)); break; default: rec->insert(line_nb, column_nb, pnew pgsString(value)); break; } } } ++column_nb; } regex2.ReplaceFirst(&line, wxT("")); } // If it is the first loop we want to process this line a // second time because the first one was meant to count // the number of columns if (count_columns == true) { count_columns = false; rec = pnew pgsRecord(nb_of_columns); } else { regex1.ReplaceFirst(&data, wxT("")); ++line_nb; } } } // Process the case if (rec == 0) { rec = pnew pgsRecord(1); rec->insert(0, 0, this->clone()); } pgsRecord ret_val(*rec); pdelete(rec); return ret_val; } pgsString pgsString::string() const { return pgsString(*this); }