mirror of
https://github.com/levinsv/pgadmin3.git
synced 2026-05-15 14:15:49 -06:00
290 lines
6.2 KiB
C++
290 lines
6.2 KiB
C++
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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 <wx/regex.h>
|
|
#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);
|
|
}
|