support PG11

Поддержка PostgreSQL 11 только для Windows
This commit is contained in:
levinsv 2018-10-10 22:59:25 +05:00
commit 4af765213c
1765 changed files with 407959 additions and 0 deletions

10
pgscript/README Normal file
View file

@ -0,0 +1,10 @@
Please refer to xtra/pgscript/doc/developers.html for the pgScript developer
documentation.
parser.sh must be called for regenerating Flex and Bison source files because it
does some more processing than just executing Bison and Flex: it replaces some
headers and add other ones.
Please use Flex 2.5.33 otherwise the pgadmin/include/pgscript/FlexLexer.h file
will not be valid. If you use a different version from 2.5.33 you need to copy FlexLexer.h that comes along with your Flex distribution to
pgadmin/include/pgscript.

View file

@ -0,0 +1,24 @@
#######################################################################
#
# pgAdmin III - PostgreSQL Tools
#
# Copyright (C) 2002 - 2016, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
# module.mk - pgadmin/pgscript/exceptions/ Makefile fragment
#
#######################################################################
pgadmin3_SOURCES += \
pgscript/exceptions/pgsArithmeticException.cpp \
pgscript/exceptions/pgsAssertException.cpp \
pgscript/exceptions/pgsBreakException.cpp \
pgscript/exceptions/pgsCastException.cpp \
pgscript/exceptions/pgsContinueException.cpp \
pgscript/exceptions/pgsException.cpp \
pgscript/exceptions/pgsInterruptException.cpp \
pgscript/exceptions/pgsParameterException.cpp
EXTRA_DIST += \
pgscript/exceptions/module.mk

View file

@ -0,0 +1,30 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/exceptions/pgsArithmeticException.h"
pgsArithmeticException::pgsArithmeticException(const wxString &left, const wxString &right) :
pgsException(), m_left(left), m_right(right)
{
}
pgsArithmeticException::~pgsArithmeticException()
{
}
const wxString pgsArithmeticException::message() const
{
return wxString() << PGSOUTEXCEPTION <<
wxString::Format(_("Arithmetic Exception - Operation impossible between '%s' and '%s'"),
m_left.c_str(), m_right.c_str());
}

View file

@ -0,0 +1,28 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/exceptions/pgsAssertException.h"
pgsAssertException::pgsAssertException(const wxString &message) :
m_message(message)
{
}
pgsAssertException::~pgsAssertException()
{
}
const wxString pgsAssertException::message() const
{
return wxString() << PGSOUTEXCEPTION << _("Assert Exception - ") << m_message;
}

View file

@ -0,0 +1,28 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/exceptions/pgsBreakException.h"
pgsBreakException::pgsBreakException() :
pgsException()
{
}
pgsBreakException::~pgsBreakException()
{
}
const wxString pgsBreakException::message() const
{
return wxT("BREAK");
}

View file

@ -0,0 +1,30 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/exceptions/pgsCastException.h"
pgsCastException::pgsCastException(const wxString &value, const wxString &type) :
pgsException(), m_value(value), m_type(type)
{
}
pgsCastException::~pgsCastException()
{
}
const wxString pgsCastException::message() const
{
return wxString() << PGSOUTEXCEPTION <<
wxString::Format(_("Cast Exception - Cannot convert '%s' to '%s'"),
m_value.c_str(), m_type.c_str());
}

View file

@ -0,0 +1,28 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/exceptions/pgsContinueException.h"
pgsContinueException::pgsContinueException() :
pgsException()
{
}
pgsContinueException::~pgsContinueException()
{
}
const wxString pgsContinueException::message() const
{
return wxT("CONTINUE");
}

View file

@ -0,0 +1,22 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/exceptions/pgsException.h"
pgsException::pgsException()
{
}
pgsException::~pgsException()
{
}

View file

@ -0,0 +1,28 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/exceptions/pgsInterruptException.h"
pgsInterruptException::pgsInterruptException() :
pgsException()
{
}
pgsInterruptException::~pgsInterruptException()
{
}
const wxString pgsInterruptException::message() const
{
return wxString() << PGSOUTEXCEPTION << _("pgScript interrupted");
}

View file

@ -0,0 +1,35 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "utils/misc.h"
#include "pgscript/exceptions/pgsParameterException.h"
pgsParameterException::pgsParameterException(const wxString &message) :
pgsException(), m_message(message)
{
}
pgsParameterException::~pgsParameterException()
{
}
const wxString pgsParameterException::message() const
{
wxString message(m_message);
message.Replace(wxT("\n"), wxT("\n") + generate_spaces(PGSOUTEXCEPTION.Length()));
message.Prepend(wxT(">> "));
message.Prepend(generate_spaces(PGSOUTEXCEPTION.Length()));
return wxString() << PGSOUTEXCEPTION <<
wxString::Format(_("Parameter Exception - Some parameters are invalid:\n%s"),
message.c_str());
}

View file

@ -0,0 +1,53 @@
#######################################################################
#
# pgAdmin III - PostgreSQL Tools
#
# Copyright (C) 2002 - 2016, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
# module.mk - pgadmin/pgscript/expressions/ Makefile fragment
#
#######################################################################
pgadmin3_SOURCES += \
pgscript/expressions/pgsAnd.cpp \
pgscript/expressions/pgsAssign.cpp \
pgscript/expressions/pgsAssignToRecord.cpp \
pgscript/expressions/pgsCast.cpp \
pgscript/expressions/pgsColumns.cpp \
pgscript/expressions/pgsDifferent.cpp \
pgscript/expressions/pgsEqual.cpp \
pgscript/expressions/pgsExecute.cpp \
pgscript/expressions/pgsExpression.cpp \
pgscript/expressions/pgsGenDate.cpp \
pgscript/expressions/pgsGenDateTime.cpp \
pgscript/expressions/pgsGenDictionary.cpp \
pgscript/expressions/pgsGenInt.cpp \
pgscript/expressions/pgsGenReal.cpp \
pgscript/expressions/pgsGenReference.cpp \
pgscript/expressions/pgsGenRegex.cpp \
pgscript/expressions/pgsGenString.cpp \
pgscript/expressions/pgsGenTime.cpp \
pgscript/expressions/pgsGreater.cpp \
pgscript/expressions/pgsGreaterEqual.cpp \
pgscript/expressions/pgsIdent.cpp \
pgscript/expressions/pgsIdentRecord.cpp \
pgscript/expressions/pgsLines.cpp \
pgscript/expressions/pgsLower.cpp \
pgscript/expressions/pgsLowerEqual.cpp \
pgscript/expressions/pgsMinus.cpp \
pgscript/expressions/pgsModulo.cpp \
pgscript/expressions/pgsNegate.cpp \
pgscript/expressions/pgsNot.cpp \
pgscript/expressions/pgsOperation.cpp \
pgscript/expressions/pgsOr.cpp \
pgscript/expressions/pgsOver.cpp \
pgscript/expressions/pgsParenthesis.cpp \
pgscript/expressions/pgsPlus.cpp \
pgscript/expressions/pgsRemoveLine.cpp \
pgscript/expressions/pgsTimes.cpp \
pgscript/expressions/pgsTrim.cpp
EXTRA_DIST += \
pgscript/expressions/module.mk

View file

@ -0,0 +1,57 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsAnd.h"
#include "pgscript/objects/pgsNumber.h"
pgsAnd::pgsAnd(const pgsExpression *left, const pgsExpression *right) :
pgsOperation(left, right)
{
}
pgsAnd::~pgsAnd()
{
}
pgsExpression *pgsAnd::clone() const
{
return pnew pgsAnd(*this);
}
pgsAnd::pgsAnd(const pgsAnd &that) :
pgsOperation(that)
{
}
pgsAnd &pgsAnd::operator =(const pgsAnd &that)
{
if (this != &that)
{
pgsOperation::operator=(that);
}
return (*this);
}
wxString pgsAnd::value() const
{
return wxString() << m_left->value() << wxT(" AND ") << m_right->value();
}
pgsOperand pgsAnd::eval(pgsVarMap &vars) const
{
return pnew pgsNumber(wxString() << (m_left->eval(vars)->pgs_is_true()
&& m_right->eval(vars)->pgs_is_true()), pgsInt);
}

View file

@ -0,0 +1,59 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsAssign.h"
#include "pgscript/objects/pgsVariable.h"
pgsAssign::pgsAssign(const wxString &name, const pgsExpression *var) :
pgsExpression(), m_name(name), m_var(var)
{
}
pgsAssign::~pgsAssign()
{
pdelete(m_var);
}
pgsExpression *pgsAssign::clone() const
{
return pnew pgsAssign(*this);
}
pgsAssign::pgsAssign(const pgsAssign &that) :
pgsExpression(that), m_name(that.m_name)
{
m_var = that.m_var->clone();
}
pgsAssign &pgsAssign::operator =(const pgsAssign &that)
{
if (this != &that)
{
pgsExpression::operator=(that);
m_name = that.m_name;
pdelete(m_var);
m_var = that.m_var->clone();
}
return (*this);
}
wxString pgsAssign::value() const
{
return wxString() << wxT("SET ") << m_name << wxT(" = ") << m_var->value();
}
pgsOperand pgsAssign::eval(pgsVarMap &vars) const
{
vars[m_name] = m_var->eval(vars);
return vars[m_name];
}

View file

@ -0,0 +1,138 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsAssignToRecord.h"
#include "pgscript/exceptions/pgsParameterException.h"
#include "pgscript/expressions/pgsIdentRecord.h"
#include "pgscript/objects/pgsRecord.h"
pgsAssignToRecord::pgsAssignToRecord(const wxString &name, const pgsExpression *line,
const pgsExpression *column, const pgsExpression *var) :
pgsAssign(name, var), m_line(line), m_column(column)
{
}
pgsAssignToRecord::~pgsAssignToRecord()
{
pdelete(m_line);
pdelete(m_column);
}
pgsExpression *pgsAssignToRecord::clone() const
{
return pnew pgsAssignToRecord(*this);
}
pgsAssignToRecord::pgsAssignToRecord(const pgsAssignToRecord &that) :
pgsAssign(that)
{
m_line = that.m_line->clone();
m_column = that.m_column->clone();
}
pgsAssignToRecord &pgsAssignToRecord::operator =(const pgsAssignToRecord &that)
{
if (this != &that)
{
pgsAssign::operator=(that);
pdelete(m_line);
pdelete(m_column);
m_line = that.m_line->clone();
m_column = that.m_column->clone();
}
return (*this);
}
wxString pgsAssignToRecord::value() const
{
return wxString() << wxT("SET ") << m_name << wxT("[") << m_line->value()
<< wxT("]") << wxT("[") << m_column->value() << wxT("]")
<< wxT(" = ") << m_var->value();
}
pgsOperand pgsAssignToRecord::eval(pgsVarMap &vars) const
{
if (vars.find(m_name) != vars.end() && vars[m_name]->is_record())
{
// Get the operand as a record
pgsRecord &rec = dynamic_cast<pgsRecord &>(*vars[m_name]);
// Get the value to assign
pgsOperand var(m_var->eval(vars));
if (!var->is_record())
{
// Evaluate parameters
pgsOperand line(m_line->eval(vars));
pgsOperand column(m_column->eval(vars));
if (line->is_integer())
{
long aux_line;
line->value().ToLong(&aux_line);
if (column->is_integer() || column->is_string())
{
bool success = false;
if (column->is_integer())
{
long aux_column;
column->value().ToLong(&aux_column);
if (aux_column < rec.count_columns())
{
success = rec.insert(aux_line, aux_column, var);
}
}
else if (column->is_string())
{
USHORT aux_column = rec.get_column(column->value());
if (aux_column < rec.count_columns())
{
success = rec.insert(aux_line, aux_column, var);
}
}
if (success == false)
{
throw pgsParameterException(wxString() << wxT("An error ")
<< wxT("occurred in record affectation: ") << value()
<< wxT("\n") << wxT("One possible reason is a ")
<< wxT("column index out of range"));
}
}
else
{
throw pgsParameterException(wxString() << column->value()
<< wxT(" is not a valid column number/name"));
}
}
else
{
throw pgsParameterException(wxString() << line->value()
<< wxT(" is not a valid line number"));
}
}
else
{
throw pgsParameterException(wxString() << wxT("Cannot assign a record")
<< wxT(" into a record: right member is a record"));
}
}
else
{
throw pgsParameterException(wxString() << m_name << wxT(" is not a record"));
}
return pgsIdentRecord(m_name, m_line->clone(), m_column->clone()).eval(vars);
}

View file

@ -0,0 +1,100 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsCast.h"
#include "pgscript/exceptions/pgsParameterException.h"
#include "pgscript/objects/pgsNumber.h"
#include "pgscript/parser.tab.hh"
typedef pgscript::pgsParser::token token;
pgsCast::pgsCast(const int &cast_type, const pgsExpression *var) :
pgsExpression(), m_cast_type(cast_type), m_var(var)
{
}
pgsCast::~pgsCast()
{
pdelete(m_var);
}
pgsExpression *pgsCast::clone() const
{
return pnew pgsCast(*this);
}
pgsCast::pgsCast(const pgsCast &that) :
pgsExpression(that), m_cast_type(that.m_cast_type)
{
m_var = that.m_var->clone();
}
pgsCast &pgsCast::operator =(const pgsCast &that)
{
if (this != &that)
{
pgsExpression::operator=(that);
m_cast_type = that.m_cast_type;
pdelete(m_var);
m_var = that.m_var->clone();
}
return (*this);
}
wxString pgsCast::value() const
{
wxString cast_type;
switch (m_cast_type)
{
case token::PGS_INTEGER:
cast_type = wxT("integer");
break;
case token::PGS_REAL:
cast_type = wxT("real");
break;
case token::PGS_RECORD:
cast_type = wxT("record");
break;
case token::PGS_STRING:
cast_type = wxT("string");
break;
default:
cast_type = wxT("unknown");
break;
}
return wxString() << wxT("CAST (") << m_var->value() << wxT(" AS ")
<< cast_type.Upper() << wxT(") ");
}
pgsOperand pgsCast::eval(pgsVarMap &vars) const
{
pgsOperand var = m_var->eval(vars);
MAPM num;
switch (m_cast_type)
{
case token::PGS_INTEGER:
num = pgsMapm::pgs_str_mapm(var->number().value());
num = pgsMapm::pgs_mapm_round(num);
return pnew pgsNumber(pgsMapm::pgs_mapm_str(num, true), pgsInt);
case token::PGS_REAL:
return pnew pgsNumber(var->number().value(), pgsReal);
case token::PGS_RECORD:
return var->record().clone();
case token::PGS_STRING:
return var->string().clone();
default:
return var->clone();
}
}

View file

@ -0,0 +1,58 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsColumns.h"
#include "pgscript/objects/pgsNumber.h"
#include "pgscript/objects/pgsRecord.h"
pgsColumns::pgsColumns(const wxString &name) :
pgsExpression(), m_name(name)
{
}
pgsColumns::~pgsColumns()
{
}
pgsExpression *pgsColumns::clone() const
{
return pnew pgsColumns(*this);
}
wxString pgsColumns::value() const
{
return wxString() << wxT("COLUMNS(") << m_name << wxT(")");
}
pgsOperand pgsColumns::eval(pgsVarMap &vars) const
{
if (vars.find(m_name) != vars.end())
{
if (vars[m_name]->is_record())
{
const pgsRecord &rec = dynamic_cast<const pgsRecord &>(*vars[m_name]);
return pnew pgsNumber(wxString() << rec.count_columns(), pgsInt);
}
else
{
// Not a record: 1 line and 1 column
return pnew pgsNumber(wxT("1"), pgsInt);
}
}
else
{
// Does not exist: 0 line and 0 column
return pnew pgsNumber(wxT("0"), pgsInt);
}
}

View file

@ -0,0 +1,60 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsDifferent.h"
#include "pgscript/objects/pgsVariable.h"
pgsDifferent::pgsDifferent(const pgsExpression *left, const pgsExpression *right) :
pgsOperation(left, right)
{
}
pgsDifferent::~pgsDifferent()
{
}
pgsExpression *pgsDifferent::clone() const
{
return pnew pgsDifferent(*this);
}
pgsDifferent::pgsDifferent(const pgsDifferent &that) :
pgsOperation(that)
{
}
pgsDifferent &pgsDifferent::operator =(const pgsDifferent &that)
{
if (this != &that)
{
pgsOperation::operator=(that);
}
return (*this);
}
wxString pgsDifferent::value() const
{
return wxString() << m_left->value() << wxT(" <> ") << m_right->value();
}
pgsOperand pgsDifferent::eval(pgsVarMap &vars) const
{
// Evaluate operands
pgsOperand left(m_left->eval(vars));
pgsOperand right(m_right->eval(vars));
// Return the result
return (*left != *right);
}

View file

@ -0,0 +1,65 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsEqual.h"
#include "pgscript/objects/pgsVariable.h"
pgsEqual::pgsEqual(const pgsExpression *left, const pgsExpression *right,
bool case_sensitive) :
pgsOperation(left, right), m_case_sensitive(case_sensitive)
{
}
pgsEqual::~pgsEqual()
{
}
pgsExpression *pgsEqual::clone() const
{
return pnew pgsEqual(*this);
}
pgsEqual::pgsEqual(const pgsEqual &that) :
pgsOperation(that), m_case_sensitive(that.m_case_sensitive)
{
}
pgsEqual &pgsEqual::operator =(const pgsEqual &that)
{
if (this != &that)
{
pgsOperation::operator=(that);
const pgsEqual *p = dynamic_cast<const pgsEqual *>(&that);
m_case_sensitive = (p != 0) ?
p->m_case_sensitive : true;
}
return (*this);
}
wxString pgsEqual::value() const
{
return wxString() << m_left->value() << (m_case_sensitive ? wxT(" = ")
: wxT(" ~= ")) << m_right->value();
}
pgsOperand pgsEqual::eval(pgsVarMap &vars) const
{
// Evaluate operands
pgsOperand left(m_left->eval(vars));
pgsOperand right(m_right->eval(vars));
// Return the result
return (m_case_sensitive ? (*left == *right) : (*left &= *right));
}

View file

@ -0,0 +1,230 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsExecute.h"
#include <wx/regex.h>
#include "db/pgConn.h"
#include "db/pgQueryThread.h"
#include "pgscript/objects/pgsNumber.h"
#include "pgscript/objects/pgsRecord.h"
#include "pgscript/objects/pgsString.h"
#include "pgscript/utilities/pgsUtilities.h"
#include "pgscript/utilities/pgsThread.h"
pgsExecute::pgsExecute(const wxString &query, pgsOutputStream *cout,
pgsThread *app) :
pgsExpression(), m_query(query), m_cout(cout), m_app(app)
{
}
pgsExecute::~pgsExecute()
{
}
pgsExpression *pgsExecute::clone() const
{
return pnew pgsExecute(*this);
}
pgsExecute &pgsExecute::operator=(const pgsExecute &that)
{
if (this != &that)
{
pgsExpression::operator=(that);
m_query = that.m_query;
m_app = that.m_app;
m_query = that.m_query;
}
return (*this);
}
wxString pgsExecute::value() const
{
return m_query;
}
pgsOperand pgsExecute::eval(pgsVarMap &vars) const
{
// Copy statement locally
wxString stmt(m_query);
// Build regular expressions
wxRegEx identifier(wxT("([^\\])(@[a-zA-Z0-9_#@]+)"));
wxRegEx escaped(wxT("\\\\(@|\\\\)")); // Backslash followed by @ or backslash
wxASSERT(identifier.IsValid() && escaped.IsValid());
// Replace variables in statement
while (identifier.Matches(stmt))
{
wxString var = identifier.GetMatch(stmt, 2);
wxString chr = identifier.GetMatch(stmt, 1);
if (vars.find(var) != vars.end())
{
wxString res = vars[var]->eval(vars)->value();
identifier.ReplaceFirst(&stmt, chr + pgsUtilities::escape_quotes(res));
}
else
{
identifier.ReplaceFirst(&stmt, chr + wxT("\\\\") + var);
}
}
escaped.ReplaceAll(&stmt, wxT("\\1"));
// Perform operations only if we have a valid connection
if (m_app != 0 && m_app->connection() != 0 && !m_app->TestDestroy())
{
pgQueryThread thread(m_app->connection(), stmt);
if (thread.Create() == wxTHREAD_NO_ERROR)
{
if (thread.Run() == wxTHREAD_NO_ERROR)
{
while (true)
{
if (m_app->TestDestroy()) // wxThread::TestDestroy()
{
thread.Delete();
break;
}
else if (thread.IsRunning())
{
m_app->Yield();
m_app->Sleep(20);
}
else
{
thread.Wait();
break;
}
}
if (thread.ReturnCode() != PGRES_COMMAND_OK
&& thread.ReturnCode() != PGRES_TUPLES_OK)
{
if (m_cout != 0)
{
m_app->LockOutput();
(*m_cout) << PGSOUTWARNING;
wxString message(stmt + wxT("\n") + thread
.GetMessagesAndClear().Strip(wxString::both));
wxRegEx multilf(wxT("(\n)+"));
multilf.ReplaceAll(&message, wxT("\n"));
message.Replace(wxT("\n"), wxT("\n")
+ generate_spaces(PGSOUTWARNING.Length()));
(*m_cout) << message << wxT("\n");
m_app->UnlockOutput();
}
}
else if (!m_app->TestDestroy())
{
if (m_cout != 0)
{
m_app->LockOutput();
(*m_cout) << PGSOUTQUERY;
wxString message(thread.GetMessagesAndClear()
.Strip(wxString::both));
if (!message.IsEmpty())
message = stmt + wxT("\n") + message;
else
message = stmt;
wxRegEx multilf(wxT("(\n)+"));
multilf.ReplaceAll(&message, wxT("\n"));
message.Replace(wxT("\n"), wxT("\n")
+ generate_spaces(PGSOUTQUERY.Length()));
(*m_cout) << message << wxT("\n");
m_app->UnlockOutput();
}
pgsRecord *rec = 0;
if (thread.DataValid())
{
pgSet *set = thread.DataSet();
set->MoveFirst();
rec = pnew pgsRecord(set->NumCols());
wxArrayLong columns_int; // List of columns that contain integers
wxArrayLong columns_real; // List of columns that contain reals
for (long i = 0; i < set->NumCols(); i++)
{
rec->set_column_name(i, set->ColName(i));
wxString col_type = set->ColType(i);
if (!col_type.CmpNoCase(wxT("bigint"))
|| !col_type.CmpNoCase(wxT("smallint"))
|| !col_type.CmpNoCase(wxT("integer")))
{
columns_int.Add(i);
}
else if (!col_type.CmpNoCase(wxT("real"))
|| !col_type.CmpNoCase(wxT("double precision"))
|| !col_type.CmpNoCase(wxT("money"))
|| !col_type.CmpNoCase(wxT("numeric")))
{
columns_real.Add(i);
}
}
size_t line = 0;
while (!set->Eof())
{
for (long i = 0; i < set->NumCols(); i++)
{
wxString value = set->GetVal(i);
if (columns_int.Index(i) != wxNOT_FOUND
&& pgsNumber::num_type(value) == pgsNumber::pgsTInt)
{
rec->insert(line, i, pnew pgsNumber(value, pgsInt));
}
else if (columns_real.Index(i) != wxNOT_FOUND
&& pgsNumber::num_type(value) == pgsNumber::pgsTReal)
{
rec->insert(line, i, pnew pgsNumber(value, pgsReal));
}
else
{
rec->insert(line, i, pnew pgsString(value));
}
}
set->MoveNext();
++line;
}
}
else
{
rec = pnew pgsRecord(1);
rec->insert(0, 0, pnew pgsNumber(wxT("1")));
}
return rec;
}
}
else
{
wxLogError(wxT("PGSCRIPT: Cannot run query thread for the query:\n%s"),
m_query.c_str());
}
}
else
{
wxLogError(wxT("PGSCRIPT: Cannot create query thread for the query:\n%s"),
m_query.c_str());
}
}
// This must return a record whatever happens
return pnew pgsRecord(1);
}

View file

@ -0,0 +1,23 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsExpression.h"
#include "pgscript/objects/pgsVariable.h"
pgsExpression::pgsExpression()
{
}
pgsExpression::~pgsExpression()
{
}

View file

@ -0,0 +1,123 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsGenDate.h"
#include "pgscript/exceptions/pgsParameterException.h"
#include "pgscript/generators/pgsDateGen.h"
#include "pgscript/objects/pgsGenerator.h"
pgsGenDate::pgsGenDate(const pgsExpression *min, const pgsExpression *max,
const pgsExpression *sequence, const pgsExpression *seed) :
pgsExpression(), m_min(min), m_max(max), m_sequence(sequence), m_seed(seed)
{
}
pgsGenDate::~pgsGenDate()
{
pdelete(m_min);
pdelete(m_max);
pdelete(m_sequence);
pdelete(m_seed);
}
pgsExpression *pgsGenDate::clone() const
{
return pnew pgsGenDate(*this);
}
pgsGenDate::pgsGenDate(const pgsGenDate &that) :
pgsExpression(that)
{
m_min = that.m_min->clone();
m_max = that.m_max->clone();
m_sequence = that.m_sequence->clone();
m_seed = that.m_seed->clone();
}
pgsGenDate &pgsGenDate::operator =(const pgsGenDate &that)
{
if (this != &that)
{
pgsExpression::operator=(that);
pdelete(m_min);
pdelete(m_max);
pdelete(m_sequence);
pdelete(m_seed);
m_min = that.m_min->clone();
m_max = that.m_max->clone();
m_sequence = that.m_sequence->clone();
m_seed = that.m_seed->clone();
}
return (*this);
}
wxString pgsGenDate::value() const
{
return wxString() << wxT("date[ min = ") << m_min->value() << wxT(" max = ")
<< m_max->value() << wxT(" sequence = ") << m_sequence->value()
<< wxT(" seed = ") << m_seed->value() << wxT(" ]");
}
pgsOperand pgsGenDate::eval(pgsVarMap &vars) const
{
// Evaluate parameters
pgsOperand min(m_min->eval(vars));
pgsOperand max(m_max->eval(vars));
pgsOperand sequence(m_sequence->eval(vars));
pgsOperand seed(m_seed->eval(vars));
// Check parameters and create the generator
if (min->is_string() && max->is_string() && sequence->is_integer()
&& seed->is_integer())
{
wxDateTime aux_min, aux_max;
if (aux_min.ParseDate(min->value()) != 0 && aux_max.ParseDate(max->value()) != 0
&& aux_min.IsValid() && aux_max.IsValid())
{
long aux_sequence, aux_seed;
sequence->value().ToLong(&aux_sequence);
seed->value().ToLong(&aux_seed);
return pnew pgsGenerator(pgsVariable::pgsTString,
pnew pgsDateGen(aux_min, aux_max, aux_sequence != 0, aux_seed));
}
else
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nmin and/or max dates are not valid"));
}
}
else
{
// Deal with errors
if (!min->is_string())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nmin should be a string"));
}
else if (!max->is_string())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nmax should be a string"));
}
else if (!sequence->is_integer())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nsequence should be an integer"));
}
else
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nseed should be an integer"));
}
}
}

View file

@ -0,0 +1,123 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsGenDateTime.h"
#include "pgscript/exceptions/pgsParameterException.h"
#include "pgscript/generators/pgsDateTimeGen.h"
#include "pgscript/objects/pgsGenerator.h"
pgsGenDateTime::pgsGenDateTime(const pgsExpression *min, const pgsExpression *max,
const pgsExpression *sequence, const pgsExpression *seed) :
pgsExpression(), m_min(min), m_max(max), m_sequence(sequence), m_seed(seed)
{
}
pgsGenDateTime::~pgsGenDateTime()
{
pdelete(m_min);
pdelete(m_max);
pdelete(m_sequence);
pdelete(m_seed);
}
pgsExpression *pgsGenDateTime::clone() const
{
return pnew pgsGenDateTime(*this);
}
pgsGenDateTime::pgsGenDateTime(const pgsGenDateTime &that) :
pgsExpression(that)
{
m_min = that.m_min->clone();
m_max = that.m_max->clone();
m_sequence = that.m_sequence->clone();
m_seed = that.m_seed->clone();
}
pgsGenDateTime &pgsGenDateTime::operator =(const pgsGenDateTime &that)
{
if (this != &that)
{
pgsExpression::operator=(that);
pdelete(m_min);
pdelete(m_max);
pdelete(m_sequence);
pdelete(m_seed);
m_min = that.m_min->clone();
m_max = that.m_max->clone();
m_sequence = that.m_sequence->clone();
m_seed = that.m_seed->clone();
}
return (*this);
}
wxString pgsGenDateTime::value() const
{
return wxString() << wxT("date_time[ min = ") << m_min->value() << wxT(" max = ")
<< m_max->value() << wxT(" sequence = ") << m_sequence->value()
<< wxT(" seed = ") << m_seed->value() << wxT(" ]");
}
pgsOperand pgsGenDateTime::eval(pgsVarMap &vars) const
{
// Evaluate parameters
pgsOperand min(m_min->eval(vars));
pgsOperand max(m_max->eval(vars));
pgsOperand sequence(m_sequence->eval(vars));
pgsOperand seed(m_seed->eval(vars));
// Check parameters and create the generator
if (min->is_string() && max->is_string() && sequence->is_integer()
&& seed->is_integer())
{
wxDateTime aux_min, aux_max;
if (aux_min.ParseDateTime(min->value()) != 0 && aux_max.ParseDateTime(max->value()) != 0
&& aux_min.IsValid() && aux_max.IsValid())
{
long aux_sequence, aux_seed;
sequence->value().ToLong(&aux_sequence);
seed->value().ToLong(&aux_seed);
return pnew pgsGenerator(pgsVariable::pgsTString,
pnew pgsDateTimeGen(aux_min, aux_max, aux_sequence != 0, aux_seed));
}
else
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nmin and/or max datetimes are not valid"));
}
}
else
{
// Deal with errors
if (!min->is_string())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nmin should be a string"));
}
else if (!max->is_string())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nmax should be a string"));
}
else if (!sequence->is_integer())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nsequence should be an integer"));
}
else
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nseed should be an integer"));
}
}
}

View file

@ -0,0 +1,126 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsGenDictionary.h"
#include <wx/filename.h>
#include "pgscript/exceptions/pgsParameterException.h"
#include "pgscript/generators/pgsDictionaryGen.h"
#include "pgscript/objects/pgsGenerator.h"
pgsGenDictionary::pgsGenDictionary(const pgsExpression *file_path, const pgsExpression *sequence,
const pgsExpression *seed, const pgsExpression *wx_conv) :
pgsExpression(), m_file_path(file_path), m_sequence(sequence), m_seed(seed),
m_wx_conv(wx_conv)
{
}
pgsGenDictionary::~pgsGenDictionary()
{
pdelete(m_file_path);
pdelete(m_sequence);
pdelete(m_seed);
pdelete(m_wx_conv);
}
pgsExpression *pgsGenDictionary::clone() const
{
return pnew pgsGenDictionary(*this);
}
pgsGenDictionary::pgsGenDictionary(const pgsGenDictionary &that) :
pgsExpression(that)
{
m_file_path = that.m_file_path->clone();
m_sequence = that.m_sequence->clone();
m_seed = that.m_seed->clone();
m_wx_conv = that.m_wx_conv->clone();
}
pgsGenDictionary &pgsGenDictionary::operator =(const pgsGenDictionary &that)
{
if (this != &that)
{
pgsExpression::operator=(that);
pdelete(m_file_path);
pdelete(m_sequence);
pdelete(m_seed);
pdelete(m_wx_conv);
m_file_path = that.m_file_path->clone();
m_sequence = that.m_sequence->clone();
m_seed = that.m_seed->clone();
m_wx_conv = that.m_wx_conv->clone();
}
return (*this);
}
wxString pgsGenDictionary::value() const
{
return wxString() << wxT("file[ file = ") << m_file_path->value() << wxT(" sequence = ")
<< m_sequence->value() << wxT(" seed = ") << m_seed->value()
<< wxT(" encoding = ") << m_wx_conv->value() << wxT(" ]");
}
pgsOperand pgsGenDictionary::eval(pgsVarMap &vars) const
{
// Evaluate parameters
pgsOperand file_path(m_file_path->eval(vars));
pgsOperand sequence(m_sequence->eval(vars));
pgsOperand seed(m_seed->eval(vars));
pgsOperand wx_conv(m_wx_conv->eval(vars));
// Check parameters and create the generator
if (file_path->is_string() && sequence->is_integer() && seed->is_integer()
&& wx_conv->is_string())
{
wxFileName file(file_path->value());
if (file.FileExists() && file.IsFileReadable())
{
long aux_sequence, aux_seed;
sequence->value().ToLong(&aux_sequence);
seed->value().ToLong(&aux_seed);
return pnew pgsGenerator(pgsVariable::pgsTString,
pnew pgsDictionaryGen(file_path->value(), aux_sequence != 0,
aux_seed, wxCSConv(wx_conv->value())));
}
else
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nFile <") << file_path->value()
<< wxT("> does not exist"));
}
}
else
{
// Deal with errors
if (!file_path->is_string())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nfile should be a string"));
}
else if (!sequence->is_integer())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nsequence should be an integer"));
}
else if (!seed->is_integer())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nseed should be an integer"));
}
else
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nencoding should be a string"));
}
}
}

View file

@ -0,0 +1,114 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsGenInt.h"
#include "pgscript/exceptions/pgsParameterException.h"
#include "pgscript/generators/pgsDictionaryGen.h"
#include "pgscript/objects/pgsGenerator.h"
pgsGenInt::pgsGenInt(const pgsExpression *min, const pgsExpression *max,
const pgsExpression *sequence, const pgsExpression *seed) :
pgsExpression(), m_min(min), m_max(max), m_sequence(sequence), m_seed(seed)
{
}
pgsGenInt::~pgsGenInt()
{
pdelete(m_min);
pdelete(m_max);
pdelete(m_sequence);
pdelete(m_seed);
}
pgsExpression *pgsGenInt::clone() const
{
return pnew pgsGenInt(*this);
}
pgsGenInt::pgsGenInt(const pgsGenInt &that) :
pgsExpression(that)
{
m_min = that.m_min->clone();
m_max = that.m_max->clone();
m_sequence = that.m_sequence->clone();
m_seed = that.m_seed->clone();
}
pgsGenInt &pgsGenInt::operator =(const pgsGenInt &that)
{
if (this != &that)
{
pgsExpression::operator=(that);
pdelete(m_min);
pdelete(m_max);
pdelete(m_sequence);
pdelete(m_seed);
m_min = that.m_min->clone();
m_max = that.m_max->clone();
m_sequence = that.m_sequence->clone();
m_seed = that.m_seed->clone();
}
return (*this);
}
wxString pgsGenInt::value() const
{
return wxString() << wxT("integer[ min = ") << m_min->value() << wxT(" max = ")
<< m_max->value() << wxT(" sequence = ") << m_sequence->value()
<< wxT(" seed = ") << m_seed->value() << wxT(" ]");
}
pgsOperand pgsGenInt::eval(pgsVarMap &vars) const
{
// Evaluate parameters
pgsOperand min(m_min->eval(vars));
pgsOperand max(m_max->eval(vars));
pgsOperand sequence(m_sequence->eval(vars));
pgsOperand seed(m_seed->eval(vars));
// Check parameters and create the generator
if (min->is_integer() && max->is_integer() && sequence->is_integer()
&& seed->is_integer())
{
long aux_sequence, aux_seed;
sequence->value().ToLong(&aux_sequence);
seed->value().ToLong(&aux_seed);
return pnew pgsGenerator(pgsVariable::pgsTInt,
pnew pgsIntegerGen(pgsVariable::num(min), pgsVariable::num(max),
aux_sequence != 0, aux_seed));
}
else
{
// Deal with errors
if (!min->is_integer())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nmin should be an integer"));
}
else if (!max->is_integer())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nmax should be an integer"));
}
else if (!sequence->is_integer())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nsequence should be an integer"));
}
else
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nseed should be an integer"));
}
}
}

View file

@ -0,0 +1,128 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsGenReal.h"
#include "pgscript/exceptions/pgsParameterException.h"
#include "pgscript/generators/pgsRealGen.h"
#include "pgscript/objects/pgsGenerator.h"
pgsGenReal::pgsGenReal(const pgsExpression *min, const pgsExpression *max,
const pgsExpression *precision, const pgsExpression *sequence,
const pgsExpression *seed) :
pgsExpression(), m_min(min), m_max(max), m_precision(precision),
m_sequence(sequence), m_seed(seed)
{
}
pgsGenReal::~pgsGenReal()
{
pdelete(m_min);
pdelete(m_max);
pdelete(m_precision);
pdelete(m_sequence);
pdelete(m_seed);
}
pgsExpression *pgsGenReal::clone() const
{
return pnew pgsGenReal(*this);
}
pgsGenReal::pgsGenReal(const pgsGenReal &that) :
pgsExpression(that)
{
m_min = that.m_min->clone();
m_max = that.m_max->clone();
m_precision = that.m_precision->clone();
m_sequence = that.m_sequence->clone();
m_seed = that.m_seed->clone();
}
pgsGenReal &pgsGenReal::operator =(const pgsGenReal &that)
{
if (this != &that)
{
pgsExpression::operator=(that);
pdelete(m_min);
pdelete(m_max);
pdelete(m_precision);
pdelete(m_sequence);
pdelete(m_seed);
m_min = that.m_min->clone();
m_max = that.m_max->clone();
m_precision = that.m_precision->clone();
m_sequence = that.m_sequence->clone();
m_seed = that.m_seed->clone();
}
return (*this);
}
wxString pgsGenReal::value() const
{
return wxString() << wxT("real[ min = ") << m_min->value() << wxT(" max = ")
<< m_max->value() << wxT(" precision = ") << m_precision->value()
<< wxT(" sequence = ") << m_sequence->value() << wxT(" seed = ")
<< m_seed->value() << wxT(" ]");
}
pgsOperand pgsGenReal::eval(pgsVarMap &vars) const
{
// Evaluate parameters
pgsOperand min(m_min->eval(vars));
pgsOperand max(m_max->eval(vars));
pgsOperand precision(m_precision->eval(vars));
pgsOperand sequence(m_sequence->eval(vars));
pgsOperand seed(m_seed->eval(vars));
// Check parameters and create the generator
if (min->is_number() && max->is_number() && sequence->is_integer()
&& seed->is_integer() && precision->is_integer())
{
long aux_sequence, aux_seed, aux_precision;
sequence->value().ToLong(&aux_sequence);
seed->value().ToLong(&aux_seed);
precision->value().ToLong(&aux_precision);
return pnew pgsGenerator(pgsVariable::pgsTReal,
pnew pgsRealGen(pgsVariable::num(min), pgsVariable::num(max), aux_precision,
aux_sequence != 0, aux_seed));
}
else
{
// Deal with errors
if (!min->is_number())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nmin should be a number"));
}
else if (!max->is_number())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nmax should be a number"));
}
else if (!precision->is_integer())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nprecision should be an integer"));
}
else if (!sequence->is_integer())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nsequence should be an integer"));
}
else
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nseed should be an integer"));
}
}
}

View file

@ -0,0 +1,131 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsGenReference.h"
#include "pgscript/exceptions/pgsParameterException.h"
#include "pgscript/generators/pgsReferenceGen.h"
#include "pgscript/expressions/pgsExecute.h"
#include "pgscript/objects/pgsGenerator.h"
pgsGenReference::pgsGenReference(const pgsExpression *table, const pgsExpression *column,
const pgsExpression *sequence, const pgsExpression *seed, pgsThread *app) :
pgsExpression(), m_table(table), m_column(column), m_sequence(sequence),
m_seed(seed), m_app(app)
{
}
pgsGenReference::~pgsGenReference()
{
pdelete(m_table);
pdelete(m_column);
pdelete(m_sequence);
pdelete(m_seed);
}
pgsExpression *pgsGenReference::clone() const
{
return pnew pgsGenReference(*this);
}
pgsGenReference::pgsGenReference(const pgsGenReference &that) :
pgsExpression(that)
{
m_table = that.m_table->clone();
m_column = that.m_column->clone();
m_sequence = that.m_sequence->clone();
m_seed = that.m_seed->clone();
m_app = that.m_app;
}
pgsGenReference &pgsGenReference::operator =(const pgsGenReference &that)
{
if (this != &that)
{
pgsExpression::operator=(that);
pdelete(m_table);
pdelete(m_column);
pdelete(m_sequence);
pdelete(m_seed);
m_table = that.m_table->clone();
m_column = that.m_column->clone();
m_sequence = that.m_sequence->clone();
m_seed = that.m_seed->clone();
m_app = that.m_app;
}
return (*this);
}
wxString pgsGenReference::value() const
{
return wxString() << wxT("reference[ table = ") << m_table->value()
<< wxT(" column = ") << m_column->value() << wxT(" sequence = ")
<< m_sequence->value() << wxT(" seed = ") << m_seed->value() << wxT(" ]");
}
pgsOperand pgsGenReference::eval(pgsVarMap &vars) const
{
// Evaluate parameters
pgsOperand table(m_table->eval(vars));
pgsOperand column(m_column->eval(vars));
pgsOperand sequence(m_sequence->eval(vars));
pgsOperand seed(m_seed->eval(vars));
// Check parameters and create the generator
if (table->is_string() && !table->value().IsEmpty() && column->is_string()
&& !column->value().IsEmpty() && sequence->is_integer()
&& seed->is_integer())
{
// Check wheter the table and the column do exist
pgsOperand result = pgsExecute(wxString() << wxT("SELECT 1 FROM ")
<< table->value() << wxT(" WHERE ") << column->value()
<< wxT(" = ") << column->value(), 0, m_app).eval(vars);
if (result->pgs_is_true())
{
long aux_sequence, aux_seed;
sequence->value().ToLong(&aux_sequence);
seed->value().ToLong(&aux_seed);
return pnew pgsGenerator(pgsVariable::pgsTString,
pnew pgsReferenceGen(m_app, table->value(),
column->value(), aux_sequence != 0, aux_seed));
}
else
{
throw pgsParameterException(wxString() << value()
<< wxT(":\ntable/column does not exist"));
}
}
else
{
// Deal with errors
if (!table->is_string() || table->value().IsEmpty())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\ntable should be a non-empty string"));
}
else if (!column->is_string() || column->value().IsEmpty())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\ncolumn should be a non-empty string"));
}
else if (!sequence->is_integer())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nsequence should be an integer"));
}
else
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nseed should be an integer"));
}
}
}

View file

@ -0,0 +1,98 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsGenRegex.h"
#include "pgscript/exceptions/pgsParameterException.h"
#include "pgscript/generators/pgsRegexGen.h"
#include "pgscript/objects/pgsGenerator.h"
pgsGenRegex::pgsGenRegex(const pgsExpression *regex, const pgsExpression *seed) :
pgsExpression(), m_regex(regex), m_seed(seed)
{
}
pgsGenRegex::~pgsGenRegex()
{
pdelete(m_regex);
pdelete(m_seed);
}
pgsExpression *pgsGenRegex::clone() const
{
return pnew pgsGenRegex(*this);
}
pgsGenRegex::pgsGenRegex(const pgsGenRegex &that) :
pgsExpression(that)
{
m_regex = that.m_regex->clone();
m_seed = that.m_seed->clone();
}
pgsGenRegex &pgsGenRegex::operator =(const pgsGenRegex &that)
{
if (this != &that)
{
pgsExpression::operator=(that);
pdelete(m_regex);
pdelete(m_seed);
m_regex = that.m_regex->clone();
m_seed = that.m_seed->clone();
}
return (*this);
}
wxString pgsGenRegex::value() const
{
return wxString() << wxT("string[ regex = ") << m_regex->value()
<< wxT(" seed = ") << m_seed->value() << wxT(" ]");
}
pgsOperand pgsGenRegex::eval(pgsVarMap &vars) const
{
// Evaluate parameters
pgsOperand regex(m_regex->eval(vars));
pgsOperand seed(m_seed->eval(vars));
// Check parameters and create the generator
if (regex->is_string() && seed->is_integer())
{
long aux_seed;
seed->value().ToLong(&aux_seed);
pgsRegexGen *gen = pnew pgsRegexGen(regex->value(), aux_seed);
if (!gen->is_valid())
{
pdelete(gen);
throw pgsParameterException(wxString() << value()
<< wxT(":\nregex is not a valid regular expression"));
}
else
{
return pnew pgsGenerator(pgsVariable::pgsTString, gen);
}
}
else
{
// Deal with errors
if (!regex->is_string())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nregex should be a string"));
}
else
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nseed should be an integer"));
}
}
}

View file

@ -0,0 +1,115 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsGenString.h"
#include "pgscript/exceptions/pgsParameterException.h"
#include "pgscript/generators/pgsStringGen.h"
#include "pgscript/objects/pgsGenerator.h"
pgsGenString::pgsGenString(const pgsExpression *min, const pgsExpression *max,
const pgsExpression *nb_words, const pgsExpression *seed) :
pgsExpression(), m_min(min), m_max(max), m_nb_words(nb_words), m_seed(seed)
{
}
pgsGenString::~pgsGenString()
{
pdelete(m_min);
pdelete(m_max);
pdelete(m_nb_words);
pdelete(m_seed);
}
pgsExpression *pgsGenString::clone() const
{
return pnew pgsGenString(*this);
}
pgsGenString::pgsGenString(const pgsGenString &that) :
pgsExpression(that)
{
m_min = that.m_min->clone();
m_max = that.m_max->clone();
m_nb_words = that.m_nb_words->clone();
m_seed = that.m_seed->clone();
}
pgsGenString &pgsGenString::operator =(const pgsGenString &that)
{
if (this != &that)
{
pgsExpression::operator=(that);
pdelete(m_min);
pdelete(m_max);
pdelete(m_nb_words);
pdelete(m_seed);
m_min = that.m_min->clone();
m_max = that.m_max->clone();
m_nb_words = that.m_nb_words->clone();
m_seed = that.m_seed->clone();
}
return (*this);
}
wxString pgsGenString::value() const
{
return wxString() << wxT("string[ min = ") << m_min->value() << wxT(" max = ")
<< m_max->value() << wxT(" nb_words = ") << m_nb_words->value()
<< wxT(" seed = ") << m_seed->value() << wxT(" ]");
}
pgsOperand pgsGenString::eval(pgsVarMap &vars) const
{
// Evaluate parameters
pgsOperand min(m_min->eval(vars));
pgsOperand max(m_max->eval(vars));
pgsOperand nb_words(m_nb_words->eval(vars));
pgsOperand seed(m_seed->eval(vars));
// Check parameters and create the generator
if (min->is_integer() && max->is_integer() && nb_words->is_integer()
&& seed->is_integer())
{
long aux_min, aux_max, aux_nb_words, aux_seed;
min->value().ToLong(&aux_min);
max->value().ToLong(&aux_max);
nb_words->value().ToLong(&aux_nb_words);
seed->value().ToLong(&aux_seed);
return pnew pgsGenerator(pgsVariable::pgsTString,
pnew pgsStringGen(aux_min, aux_max, aux_nb_words, aux_seed));
}
else
{
// Deal with errors
if (!min->is_integer())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nmin should be an integer"));
}
else if (!max->is_integer())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nmax should be an integer"));
}
else if (!nb_words->is_integer())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nnb_words should be an integer"));
}
else
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nseed should be an integer"));
}
}
}

View file

@ -0,0 +1,123 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsGenTime.h"
#include "pgscript/exceptions/pgsParameterException.h"
#include "pgscript/generators/pgsTimeGen.h"
#include "pgscript/objects/pgsGenerator.h"
pgsGenTime::pgsGenTime(const pgsExpression *min, const pgsExpression *max,
const pgsExpression *sequence, const pgsExpression *seed) :
pgsExpression(), m_min(min), m_max(max), m_sequence(sequence), m_seed(seed)
{
}
pgsGenTime::~pgsGenTime()
{
pdelete(m_min);
pdelete(m_max);
pdelete(m_sequence);
pdelete(m_seed);
}
pgsExpression *pgsGenTime::clone() const
{
return pnew pgsGenTime(*this);
}
pgsGenTime::pgsGenTime(const pgsGenTime &that) :
pgsExpression(that)
{
m_min = that.m_min->clone();
m_max = that.m_max->clone();
m_sequence = that.m_sequence->clone();
m_seed = that.m_seed->clone();
}
pgsGenTime &pgsGenTime::operator =(const pgsGenTime &that)
{
if (this != &that)
{
pgsExpression::operator=(that);
pdelete(m_min);
pdelete(m_max);
pdelete(m_sequence);
pdelete(m_seed);
m_min = that.m_min->clone();
m_max = that.m_max->clone();
m_sequence = that.m_sequence->clone();
m_seed = that.m_seed->clone();
}
return (*this);
}
wxString pgsGenTime::value() const
{
return wxString() << wxT("time[ min = ") << m_min->value() << wxT(" max = ")
<< m_max->value() << wxT(" sequence = ") << m_sequence->value()
<< wxT(" seed = ") << m_seed->value() << wxT(" ]");
}
pgsOperand pgsGenTime::eval(pgsVarMap &vars) const
{
// Evaluate parameters
pgsOperand min(m_min->eval(vars));
pgsOperand max(m_max->eval(vars));
pgsOperand sequence(m_sequence->eval(vars));
pgsOperand seed(m_seed->eval(vars));
// Check parameters and create the generator
if (min->is_string() && max->is_string() && sequence->is_integer()
&& seed->is_integer())
{
wxDateTime aux_min, aux_max;
if (aux_min.ParseTime(min->value()) != 0 && aux_max.ParseTime(max->value()) != 0
&& aux_min.IsValid() && aux_max.IsValid())
{
long aux_sequence, aux_seed;
sequence->value().ToLong(&aux_sequence);
seed->value().ToLong(&aux_seed);
return pnew pgsGenerator(pgsVariable::pgsTString,
pnew pgsTimeGen(aux_min, aux_max, aux_sequence != 0, aux_seed));
}
else
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nmin and/or max times are not valid"));
}
}
else
{
// Deal with errors
if (!min->is_string())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nmin should be a string"));
}
else if (!max->is_string())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nmax should be a string"));
}
else if (!sequence->is_integer())
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nsequence should be an integer"));
}
else
{
throw pgsParameterException(wxString() << value()
<< wxT(":\nseed should be an integer"));
}
}
}

View file

@ -0,0 +1,60 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsGreater.h"
#include "pgscript/objects/pgsVariable.h"
pgsGreater::pgsGreater(const pgsExpression *left, const pgsExpression *right) :
pgsOperation(left, right)
{
}
pgsGreater::~pgsGreater()
{
}
pgsExpression *pgsGreater::clone() const
{
return pnew pgsGreater(*this);
}
pgsGreater::pgsGreater(const pgsGreater &that) :
pgsOperation(that)
{
}
pgsGreater &pgsGreater::operator =(const pgsGreater &that)
{
if (this != &that)
{
pgsOperation::operator=(that);
}
return (*this);
}
wxString pgsGreater::value() const
{
return wxString() << m_left->value() << wxT(" > ") << m_right->value();
}
pgsOperand pgsGreater::eval(pgsVarMap &vars) const
{
// Evaluate operands
pgsOperand left(m_left->eval(vars));
pgsOperand right(m_right->eval(vars));
// Return the result
return (*left > *right);
}

View file

@ -0,0 +1,60 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsGreaterEqual.h"
#include "pgscript/objects/pgsVariable.h"
pgsGreaterEqual::pgsGreaterEqual(const pgsExpression *left, const pgsExpression *right) :
pgsOperation(left, right)
{
}
pgsGreaterEqual::~pgsGreaterEqual()
{
}
pgsExpression *pgsGreaterEqual::clone() const
{
return pnew pgsGreaterEqual(*this);
}
pgsGreaterEqual::pgsGreaterEqual(const pgsGreaterEqual &that) :
pgsOperation(that)
{
}
pgsGreaterEqual &pgsGreaterEqual::operator =(const pgsGreaterEqual &that)
{
if (this != &that)
{
pgsOperation::operator=(that);
}
return (*this);
}
wxString pgsGreaterEqual::value() const
{
return wxString() << m_left->value() << wxT(" >= ") << m_right->value();
}
pgsOperand pgsGreaterEqual::eval(pgsVarMap &vars) const
{
// Evaluate operands
pgsOperand left(m_left->eval(vars));
pgsOperand right(m_right->eval(vars));
// Return the result
return (*left >= *right);
}

View file

@ -0,0 +1,56 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsIdent.h"
#include <wx/datetime.h>
#include "pgscript/objects/pgsNumber.h"
#include "pgscript/objects/pgsString.h"
const wxString pgsIdent::m_now = wxT("@NOW");
pgsIdent::pgsIdent(const wxString &name) :
pgsExpression(), m_name(name)
{
}
pgsIdent::~pgsIdent()
{
}
pgsExpression *pgsIdent::clone() const
{
return pnew pgsIdent(*this);
}
wxString pgsIdent::value() const
{
return m_name;
}
pgsOperand pgsIdent::eval(pgsVarMap &vars) const
{
if (vars.find(m_name) != vars.end())
{
return vars[m_name];
}
else if (m_name == m_now)
{
time_t now = wxDateTime::GetTimeNow();
return pnew pgsNumber(wxString() << now);
}
else
{
return pnew pgsString(wxT(""));
}
}

View file

@ -0,0 +1,103 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsIdentRecord.h"
#include "pgscript/objects/pgsRecord.h"
#include "pgscript/objects/pgsString.h"
pgsIdentRecord::pgsIdentRecord(const wxString &name, const pgsExpression *line,
const pgsExpression *column) :
pgsIdent(name), m_line(line), m_column(column)
{
}
pgsIdentRecord::~pgsIdentRecord()
{
pdelete(m_line);
pdelete(m_column);
}
pgsExpression *pgsIdentRecord::clone() const
{
return pnew pgsIdentRecord(*this);
}
pgsIdentRecord::pgsIdentRecord(const pgsIdentRecord &that) :
pgsIdent(that)
{
m_line = that.m_line->clone();
m_column = that.m_column != 0 ? that.m_column->clone() : 0;
}
pgsIdentRecord &pgsIdentRecord::operator=(const pgsIdentRecord &that)
{
if (this != &that)
{
pgsIdent::operator=(that);
pdelete(m_line);
pdelete(m_column);
m_line = that.m_line->clone();
m_column = that.m_column != 0 ? that.m_column->clone() : 0;
}
return (*this);
}
wxString pgsIdentRecord::value() const
{
wxString result;
result << m_name << wxT("[") << m_line->value() << wxT("]");
if (m_column != 0)
{
result << wxT("[") << m_column->value() << wxT("]");
}
return result;
}
pgsOperand pgsIdentRecord::eval(pgsVarMap &vars) const
{
// Check whether the variable is a record
if (vars.find(m_name) != vars.end() && vars[m_name]->is_record())
{
// Get the operand as a record
const pgsRecord &rec = dynamic_cast<const pgsRecord &>(*vars[m_name]);
// Evaluate parameters
pgsOperand line(m_line->eval(vars));
if (line->is_integer())
{
long aux_line;
line->value().ToLong(&aux_line);
if (m_column != 0)
{
pgsOperand column(m_column->eval(vars));
if (column->is_integer())
{
long aux_column;
column->value().ToLong(&aux_column);
return rec.get(aux_line, aux_column);
}
else if (column->is_string())
{
return rec.get(aux_line, rec.get_column(column->value()));
}
}
else
{
return rec.get_line(aux_line);
}
}
}
return pnew pgsString(wxT(""));
}

View file

@ -0,0 +1,58 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsLines.h"
#include "pgscript/objects/pgsNumber.h"
#include "pgscript/objects/pgsRecord.h"
pgsLines::pgsLines(const wxString &name) :
pgsExpression(), m_name(name)
{
}
pgsLines::~pgsLines()
{
}
pgsExpression *pgsLines::clone() const
{
return pnew pgsLines(*this);
}
wxString pgsLines::value() const
{
return wxString() << wxT("LINES(") << m_name << wxT(")");
}
pgsOperand pgsLines::eval(pgsVarMap &vars) const
{
if (vars.find(m_name) != vars.end())
{
if (vars[m_name]->is_record())
{
const pgsRecord &rec = dynamic_cast<const pgsRecord &>(*vars[m_name]);
return pnew pgsNumber(wxString() << rec.count_lines(), pgsInt);
}
else
{
// Not a record: 1 line and 1 column
return pnew pgsNumber(wxT("1"), pgsInt);
}
}
else
{
// Does not exist: 0 line and 0 column
return pnew pgsNumber(wxT("0"), pgsInt);
}
}

View file

@ -0,0 +1,60 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsLower.h"
#include "pgscript/objects/pgsVariable.h"
pgsLower::pgsLower(const pgsExpression *left, const pgsExpression *right) :
pgsOperation(left, right)
{
}
pgsLower::~pgsLower()
{
}
pgsExpression *pgsLower::clone() const
{
return pnew pgsLower(*this);
}
pgsLower::pgsLower(const pgsLower &that) :
pgsOperation(that)
{
}
pgsLower &pgsLower::operator =(const pgsLower &that)
{
if (this != &that)
{
pgsOperation::operator=(that);
}
return (*this);
}
wxString pgsLower::value() const
{
return wxString() << m_left->value() << wxT(" < ") << m_right->value();
}
pgsOperand pgsLower::eval(pgsVarMap &vars) const
{
// Evaluate operands
pgsOperand left(m_left->eval(vars));
pgsOperand right(m_right->eval(vars));
// Return the result
return (*left < *right);
}

View file

@ -0,0 +1,61 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsLowerEqual.h"
#include "pgscript/objects/pgsRecord.h"
#include "pgscript/objects/pgsVariable.h"
pgsLowerEqual::pgsLowerEqual(const pgsExpression *left, const pgsExpression *right) :
pgsOperation(left, right)
{
}
pgsLowerEqual::~pgsLowerEqual()
{
}
pgsExpression *pgsLowerEqual::clone() const
{
return pnew pgsLowerEqual(*this);
}
pgsLowerEqual::pgsLowerEqual(const pgsLowerEqual &that) :
pgsOperation(that)
{
}
pgsLowerEqual &pgsLowerEqual::operator =(const pgsLowerEqual &that)
{
if (this != &that)
{
pgsOperation::operator=(that);
}
return (*this);
}
wxString pgsLowerEqual::value() const
{
return wxString() << m_left->value() << wxT(" <= ") << m_right->value();
}
pgsOperand pgsLowerEqual::eval(pgsVarMap &vars) const
{
// Evaluate operands
pgsOperand left(m_left->eval(vars));
pgsOperand right(m_right->eval(vars));
// Return the result
return (*left <= *right);
}

View file

@ -0,0 +1,60 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsMinus.h"
#include "pgscript/objects/pgsVariable.h"
pgsMinus::pgsMinus(const pgsExpression *left, const pgsExpression *right) :
pgsOperation(left, right)
{
}
pgsMinus::~pgsMinus()
{
}
pgsExpression *pgsMinus::clone() const
{
return pnew pgsMinus(*this);
}
pgsMinus::pgsMinus(const pgsMinus &that) :
pgsOperation(that)
{
}
pgsMinus &pgsMinus::operator =(const pgsMinus &that)
{
if (this != &that)
{
pgsOperation::operator=(that);
}
return (*this);
}
wxString pgsMinus::value() const
{
return wxString() << m_left->value() << wxT(" - ") << m_right->value();
}
pgsOperand pgsMinus::eval(pgsVarMap &vars) const
{
// Evaluate operands
pgsOperand left(m_left->eval(vars));
pgsOperand right(m_right->eval(vars));
// Return the result
return (*left - *right);
}

View file

@ -0,0 +1,60 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsModulo.h"
#include "pgscript/objects/pgsVariable.h"
pgsModulo::pgsModulo(const pgsExpression *left, const pgsExpression *right) :
pgsOperation(left, right)
{
}
pgsModulo::~pgsModulo()
{
}
pgsExpression *pgsModulo::clone() const
{
return pnew pgsModulo(*this);
}
pgsModulo::pgsModulo(const pgsModulo &that) :
pgsOperation(that)
{
}
pgsModulo &pgsModulo::operator =(const pgsModulo &that)
{
if (this != &that)
{
pgsOperation::operator=(that);
}
return (*this);
}
wxString pgsModulo::value() const
{
return wxString() << m_left->value() << wxT(" % ") << m_right->value();
}
pgsOperand pgsModulo::eval(pgsVarMap &vars) const
{
// Evaluate operands
pgsOperand left(m_left->eval(vars));
pgsOperand right(m_right->eval(vars));
// Return the result
return (*left % *right);
}

View file

@ -0,0 +1,60 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsNegate.h"
#include "pgscript/objects/pgsNumber.h"
pgsNegate::pgsNegate(const pgsExpression *left) :
pgsOperation(left, 0)
{
}
pgsNegate::~pgsNegate()
{
}
pgsExpression *pgsNegate::clone() const
{
return pnew pgsNegate(*this);
}
pgsNegate::pgsNegate(const pgsNegate &that) :
pgsOperation(that)
{
}
pgsNegate &pgsNegate::operator =(const pgsNegate &that)
{
if (this != &that)
{
pgsOperation::operator=(that);
}
return (*this);
}
wxString pgsNegate::value() const
{
return wxString() << wxT("-") << m_left->value();
}
pgsOperand pgsNegate::eval(pgsVarMap &vars) const
{
// Evaluate operands
pgsOperand left(pnew pgsNumber(wxT("0"), pgsInt));
pgsOperand right(m_left->eval(vars));
// Return the result
return (*left - *right);
}

View file

@ -0,0 +1,59 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsNot.h"
#include "pgscript/objects/pgsVariable.h"
pgsNot::pgsNot(const pgsExpression *left) :
pgsOperation(left, 0)
{
}
pgsNot::~pgsNot()
{
}
pgsExpression *pgsNot::clone() const
{
return pnew pgsNot(*this);
}
pgsNot::pgsNot(const pgsNot &that) :
pgsOperation(that)
{
}
pgsNot &pgsNot::operator =(const pgsNot &that)
{
if (this != &that)
{
pgsOperation::operator=(that);
}
return (*this);
}
wxString pgsNot::value() const
{
return wxString() << wxT("NOT ") << m_left->value();
}
pgsOperand pgsNot::eval(pgsVarMap &vars) const
{
// Evaluate operands
pgsOperand left(m_left->eval(vars));
// Return the result
return (!(*left));
}

View file

@ -0,0 +1,46 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsOperation.h"
#include "pgscript/objects/pgsVariable.h"
pgsOperation::pgsOperation(const pgsExpression *left, const pgsExpression *right) :
pgsExpression(), m_left(left), m_right(right)
{
}
pgsOperation::~pgsOperation()
{
pdelete(m_left);
pdelete(m_right);
}
pgsOperation::pgsOperation(const pgsOperation &that) :
pgsExpression(that)
{
m_left = that.m_left->clone();
m_right = that.m_right != 0 ? that.m_right->clone() : 0;
}
pgsOperation &pgsOperation::operator =(const pgsOperation &that)
{
if (this != &that)
{
pgsExpression::operator=(that);
pdelete(m_left);
pdelete(m_right);
m_left = that.m_left->clone();
m_right = that.m_right != 0 ? that.m_right->clone() : 0;
}
return (*this);
}

View file

@ -0,0 +1,56 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsOr.h"
#include "pgscript/objects/pgsNumber.h"
pgsOr::pgsOr(const pgsExpression *left, const pgsExpression *right) :
pgsOperation(left, right)
{
}
pgsOr::~pgsOr()
{
}
pgsExpression *pgsOr::clone() const
{
return pnew pgsOr(*this);
}
pgsOr::pgsOr(const pgsOr &that) :
pgsOperation(that)
{
}
pgsOr &pgsOr::operator =(const pgsOr &that)
{
if (this != &that)
{
pgsOperation::operator=(that);
}
return (*this);
}
wxString pgsOr::value() const
{
return wxString() << m_left->value() << wxT(" OR ") << m_right->value();
}
pgsOperand pgsOr::eval(pgsVarMap &vars) const
{
return pnew pgsNumber(wxString() << (m_left->eval(vars)->pgs_is_true()
|| m_right->eval(vars)->pgs_is_true()), pgsInt);
}

View file

@ -0,0 +1,60 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsOver.h"
#include "pgscript/objects/pgsVariable.h"
pgsOver::pgsOver(const pgsExpression *left, const pgsExpression *right) :
pgsOperation(left, right)
{
}
pgsOver::~pgsOver()
{
}
pgsExpression *pgsOver::clone() const
{
return pnew pgsOver(*this);
}
pgsOver::pgsOver(const pgsOver &that) :
pgsOperation(that)
{
}
pgsOver &pgsOver::operator =(const pgsOver &that)
{
if (this != &that)
{
pgsOperation::operator=(that);
}
return (*this);
}
wxString pgsOver::value() const
{
return wxString() << m_left->value() << wxT(" / ") << m_right->value();
}
pgsOperand pgsOver::eval(pgsVarMap &vars) const
{
// Evaluate operands
pgsOperand left(m_left->eval(vars));
pgsOperand right(m_right->eval(vars));
// Return the result
return (*left / *right);
}

View file

@ -0,0 +1,59 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsParenthesis.h"
#include "pgscript/objects/pgsVariable.h"
pgsParenthesis::pgsParenthesis(const pgsExpression *left) :
pgsOperation(left, 0)
{
}
pgsParenthesis::~pgsParenthesis()
{
}
pgsExpression *pgsParenthesis::clone() const
{
return pnew pgsParenthesis(*this);
}
pgsParenthesis::pgsParenthesis(const pgsParenthesis &that) :
pgsOperation(that)
{
}
pgsParenthesis &pgsParenthesis::operator =(const pgsParenthesis &that)
{
if (this != &that)
{
pgsOperation::operator=(that);
}
return (*this);
}
wxString pgsParenthesis::value() const
{
return wxString() << wxT("(") << m_left->value() << wxT(")");
}
pgsOperand pgsParenthesis::eval(pgsVarMap &vars) const
{
// Evaluate operands
pgsOperand left(m_left->eval(vars));
// Return the result
return left;
}

View file

@ -0,0 +1,60 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsPlus.h"
#include "pgscript/objects/pgsVariable.h"
pgsPlus::pgsPlus(const pgsExpression *left, const pgsExpression *right) :
pgsOperation(left, right)
{
}
pgsPlus::~pgsPlus()
{
}
pgsExpression *pgsPlus::clone() const
{
return pnew pgsPlus(*this);
}
pgsPlus::pgsPlus(const pgsPlus &that) :
pgsOperation(that)
{
}
pgsPlus &pgsPlus::operator =(const pgsPlus &that)
{
if (this != &that)
{
pgsOperation::operator=(that);
}
return (*this);
}
wxString pgsPlus::value() const
{
return wxString() << m_left->value() << wxT(" + ") << m_right->value();
}
pgsOperand pgsPlus::eval(pgsVarMap &vars) const
{
// Evaluate operands
pgsOperand left(m_left->eval(vars));
pgsOperand right(m_right->eval(vars));
// Return the result
return (*left + *right);
}

View file

@ -0,0 +1,89 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsRemoveLine.h"
#include "pgscript/exceptions/pgsParameterException.h"
#include "pgscript/objects/pgsRecord.h"
#include "pgscript/objects/pgsString.h"
pgsRemoveLine::pgsRemoveLine(const wxString &rec, const pgsExpression *line) :
pgsExpression(), m_rec(rec), m_line(line)
{
}
pgsRemoveLine::~pgsRemoveLine()
{
pdelete(m_line);
}
pgsExpression *pgsRemoveLine::clone() const
{
return pnew pgsRemoveLine(*this);
}
pgsRemoveLine::pgsRemoveLine(const pgsRemoveLine &that) :
pgsExpression(that), m_rec(that.m_rec)
{
m_line = that.m_line->clone();
}
pgsRemoveLine &pgsRemoveLine::operator =(const pgsRemoveLine &that)
{
if (this != &that)
{
pgsExpression::operator=(that);
m_rec = that.m_rec;
pdelete(m_line);
m_line = that.m_line->clone();
}
return (*this);
}
wxString pgsRemoveLine::value() const
{
return wxString() << wxT("RMLINE(") << m_rec << wxT("[")
<< m_line->value() << wxT("])");
}
pgsOperand pgsRemoveLine::eval(pgsVarMap &vars) const
{
if (vars.find(m_rec) != vars.end() && vars[m_rec]->is_record())
{
pgsRecord &rec = dynamic_cast<pgsRecord &>(*vars[m_rec]);
// Evaluate parameter
pgsOperand line(m_line->eval(vars));
if (line->is_integer())
{
long aux_line;
line->value().ToLong(&aux_line);
if (!rec.remove_line(aux_line))
{
throw pgsParameterException(wxString() << wxT("an error ")
<< wxT("occurred while executing ") << value());
}
}
else
{
throw pgsParameterException(wxString() << line->value()
<< wxT(" is not a valid line number"));
}
return vars[m_rec];
}
else
{
throw pgsParameterException(wxString() << m_rec << wxT(" is not a record"));
}
}

View file

@ -0,0 +1,60 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsTimes.h"
#include "pgscript/objects/pgsVariable.h"
pgsTimes::pgsTimes(const pgsExpression *left, const pgsExpression *right) :
pgsOperation(left, right)
{
}
pgsTimes::~pgsTimes()
{
}
pgsExpression *pgsTimes::clone() const
{
return pnew pgsTimes(*this);
}
pgsTimes::pgsTimes(const pgsTimes &that) :
pgsOperation(that)
{
}
pgsTimes &pgsTimes::operator =(const pgsTimes &that)
{
if (this != &that)
{
pgsOperation::operator=(that);
}
return (*this);
}
wxString pgsTimes::value() const
{
return wxString() << m_left->value() << wxT(" * ") << m_right->value();
}
pgsOperand pgsTimes::eval(pgsVarMap &vars) const
{
// Evaluate operands
pgsOperand left(m_left->eval(vars));
pgsOperand right(m_right->eval(vars));
// Return the result
return (*left **right);
}

View file

@ -0,0 +1,57 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/expressions/pgsTrim.h"
#include "pgscript/objects/pgsString.h"
pgsTrim::pgsTrim(const pgsExpression *exp) :
pgsExpression(), m_exp(exp)
{
}
pgsTrim::~pgsTrim()
{
pdelete(m_exp);
}
pgsTrim::pgsTrim(const pgsTrim &that) :
pgsExpression(that)
{
m_exp = that.m_exp->clone();
}
pgsTrim &pgsTrim::operator=(const pgsTrim &that)
{
if (this != &that)
{
pgsExpression::operator=(that);
pdelete(m_exp);
m_exp = that.m_exp->clone();
}
return (*this);
}
pgsExpression *pgsTrim::clone() const
{
return pnew pgsTrim(*this);
}
wxString pgsTrim::value() const
{
return wxString() << wxT("TRIM(") << m_exp->value() << wxT(")");
}
pgsOperand pgsTrim::eval(pgsVarMap &vars) const
{
return pnew pgsString(m_exp->eval(vars)->value().Strip(wxString::both));
}

View file

@ -0,0 +1,27 @@
#######################################################################
#
# pgAdmin III - PostgreSQL Tools
#
# Copyright (C) 2002 - 2016, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
# module.mk - pgadmin/pgscript/generators/ Makefile fragment
#
#######################################################################
pgadmin3_SOURCES += \
pgscript/generators/pgsDateGen.cpp \
pgscript/generators/pgsDateTimeGen.cpp \
pgscript/generators/pgsDictionaryGen.cpp \
pgscript/generators/pgsIntegerGen.cpp \
pgscript/generators/pgsNumberGen.cpp \
pgscript/generators/pgsObjectGen.cpp \
pgscript/generators/pgsRealGen.cpp \
pgscript/generators/pgsReferenceGen.cpp \
pgscript/generators/pgsRegexGen.cpp \
pgscript/generators/pgsStringGen.cpp \
pgscript/generators/pgsTimeGen.cpp
EXTRA_DIST += \
pgscript/generators/module.mk

View file

@ -0,0 +1,47 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/generators/pgsDateGen.h"
pgsDateGen::pgsDateGen(wxDateTime min, wxDateTime max, const bool &sequence,
const long &seed) :
pgsObjectGen(seed), m_min(min.IsEarlierThan(max) || min.IsEqualTo(max) ? min : max),
m_max(max.IsLaterThan(min) || max.IsEqualTo(min) ? max : min),
m_range(m_max.Subtract(m_min).GetDays()), m_sequence(sequence)
{
m_randomizer = pgsRandomizer(pnew pgsIntegerGen(0, m_range, is_sequence(),
m_seed));
}
bool pgsDateGen::is_sequence() const
{
return m_sequence;
}
wxString pgsDateGen::random()
{
wxDateSpan date_span(0, 0, 0, m_randomizer->random_long());
wxDateTime aux_min(m_min);
aux_min.Add(date_span);
wxASSERT(aux_min.IsLaterThan(m_min) || aux_min.IsEqualTo(m_min));
wxASSERT(aux_min.IsEarlierThan(m_max) || aux_min.IsEqualTo(m_max));
return aux_min.FormatISODate();
}
pgsDateGen::~pgsDateGen()
{
}
pgsDateGen *pgsDateGen::clone()
{
return pnew pgsDateGen(*this);
}

View file

@ -0,0 +1,62 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/generators/pgsDateTimeGen.h"
#include <string>
pgsDateTimeGen::pgsDateTimeGen(wxDateTime min, wxDateTime max,
const bool &sequence, const long &seed) :
pgsObjectGen(seed), m_min(min.IsEarlierThan(max) || min.IsEqualTo(max) ? min : max),
m_max(max.IsLaterThan(min) || max.IsEqualTo(min) ? max : min),
m_range(m_max.Subtract(m_min).GetSeconds()), m_sequence(sequence)
{
m_randomizer = pgsRandomizer(pnew pgsIntegerGen(0, std::string(m_range
.ToString().mb_str()).c_str(), is_sequence(), m_seed));
}
bool pgsDateTimeGen::is_sequence() const
{
return m_sequence;
}
wxString pgsDateTimeGen::random()
{
// Get a random number representing seconds
MAPM result = pgsMapm::pgs_str_mapm(m_randomizer->random()), quot, rem;
// Use hours and seconds for avoiding overflows of seconds
result.integer_div_rem(3600, quot, rem);
long hours, seconds;
pgsMapm::pgs_mapm_str(quot, true).ToLong(&hours);
pgsMapm::pgs_mapm_str(rem, true).ToLong(&seconds);
wxTimeSpan time_span(hours, 0, seconds, 0);
// Add the TimeSpan to the MinDate
wxDateTime aux_min(m_min);
aux_min.Add(time_span);
// Post conditions
wxASSERT(aux_min.IsLaterThan(m_min) || aux_min.IsEqualTo(m_min));
wxASSERT(aux_min.IsEarlierThan(m_max) || aux_min.IsEqualTo(m_max));
return aux_min.Format(wxT("%Y-%m-%d %H:%M:%S"));
}
pgsDateTimeGen::~pgsDateTimeGen()
{
}
pgsDateTimeGen *pgsDateTimeGen::clone()
{
return pnew pgsDateTimeGen(*this);
}

View file

@ -0,0 +1,99 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/generators/pgsDictionaryGen.h"
#include <wx/txtstrm.h>
#include <wx/wfstream.h>
#include <wx/filename.h>
pgsDictionaryGen::pgsDictionaryGen(const wxString &file_path,
const bool &sequence, const long &seed, wxCSConv conv) :
pgsObjectGen(seed), m_file_path(file_path), m_conv(conv)
{
m_nb_lines = this->count_lines();
m_randomizer = pgsRandomizer(pnew pgsIntegerGen(1, m_nb_lines,
sequence, seed));
}
wxString pgsDictionaryGen::random()
{
return this->get_line(m_randomizer->random_long());
}
pgsDictionaryGen::~pgsDictionaryGen()
{
}
pgsDictionaryGen *pgsDictionaryGen::clone()
{
return pnew pgsDictionaryGen(*this);
}
const long &pgsDictionaryGen::nb_lines() const
{
return m_nb_lines;
}
long pgsDictionaryGen::count_lines()
{
long result = 0;
wxFileName file_path(m_file_path);
if (file_path.FileExists() && file_path.IsFileReadable())
{
wxFFileInputStream input(m_file_path);
if (input.IsOk())
{
#if wxUSE_UNICODE
wxTextInputStream text(input, wxT(" \t"), m_conv);
#else
wxTextInputStream text(input, wxT(" \t"));
#endif
wxString line;
while (!(line = text.ReadLine()).IsEmpty() && !input.Eof())
{
++result;
}
}
}
if (result < 0) result = 0;
wxASSERT(result >= 0);
return result;
}
wxString pgsDictionaryGen::get_line(long line_nb)
{
long current_line = 1;
if (m_nb_lines > 0)
{
wxFFileInputStream input(m_file_path);
if (input.IsOk())
{
#if wxUSE_UNICODE
wxTextInputStream text(input, wxT(" \t"), m_conv);
#else
wxTextInputStream text(input, wxT(" \t"));
#endif
while (current_line < line_nb && !input.Eof())
{
text.ReadLine();
++current_line;
}
return text.ReadLine();
}
}
return wxString();
}

View file

@ -0,0 +1,174 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/generators/pgsIntegerGen.h"
pgsIntegerGen::pgsSequentialIntGen::pgsSequentialIntGen(const MAPM &range,
const long &seed) :
pgsNumberGen(range), m_state(seed), m_m(2), m_remainder(m_range)
{
MAPM _2 = 2;
while (m_m < m_range)
{
m_m = m_m * _2;
}
m_buffer.Alloc(BUFFER_SIZE);
}
MAPM pgsIntegerGen::pgsSequentialIntGen::random()
{
// Bufferizer BUFFER_SIZE values in the vector
if (m_buffer.GetCount() == 0)
{
// Calculate the number of elements to bufferize
MAPM min = wxMin(m_remainder, MAPM(BUFFER_SIZE));
// Generate those elements
for (MAPM i = 0; i < min; i = i + 1)
{
do
{
m_state = (m_state * arg_a);
m_state = (m_state + arg_c) % m_m;
}
while (m_state >= m_range);
m_buffer.Add(m_state);
m_remainder -= 1;
}
class pgsRandInt
{
private:
long m_state;
public:
pgsRandInt(long n)
: m_state(n)
{
}
long rand()
{
m_state = (1103515245L * m_state + 12345L) % 2147483647L;
return m_state;
}
};
// Shuffle the vector of generated values
pgsRandInt rand_int(BUFFER_SIZE);
for (size_t i = 0; i < m_buffer.GetCount(); i++)
{
size_t r = i + (rand_int.rand() % (m_buffer.GetCount() - i));
const MAPM a = m_buffer.Item(i);
m_buffer.Item(i) = m_buffer.Item(r);
m_buffer.Item(r) = a;
}
}
if (m_remainder == 0)
{
m_remainder = m_range;
}
// Take the last bufferized value
MAPM data = m_buffer.Last();
m_buffer.RemoveAt(m_buffer.GetCount() - 1);
// Return random value
return data;
}
pgsIntegerGen::pgsSequentialIntGen::~pgsSequentialIntGen()
{
}
pgsNumberGen *pgsIntegerGen::pgsSequentialIntGen::clone()
{
return pnew pgsIntegerGen::pgsSequentialIntGen(*this);
}
const MAPM pgsIntegerGen::pgsSequentialIntGen::arg_a = 5;
const MAPM pgsIntegerGen::pgsSequentialIntGen::arg_c = 1;
pgsIntegerGen::pgsNormalIntGen::pgsNormalIntGen(const MAPM &range,
const long &seed) :
pgsNumberGen(range), m_state(seed), m_top(arg_m - 1)
{
for (int i = 0; i < 10; i++)
random(); // Beginning of the sequence is garbage
}
MAPM pgsIntegerGen::pgsNormalIntGen::random()
{
m_state = (m_state * arg_a);
m_state = (m_state + arg_c) % arg_m;
return (m_state * m_range).div(m_top);
}
pgsIntegerGen::pgsNormalIntGen::~pgsNormalIntGen()
{
}
pgsNumberGen *pgsIntegerGen::pgsNormalIntGen::clone()
{
return pnew pgsIntegerGen::pgsNormalIntGen(*this);
}
const MAPM pgsIntegerGen::pgsNormalIntGen::arg_a = 16807L;
const MAPM pgsIntegerGen::pgsNormalIntGen::arg_c = 0;
const MAPM pgsIntegerGen::pgsNormalIntGen::arg_m = 2147483647L;
pgsIntegerGen::pgsIntegerGen(const MAPM &min, const MAPM &max,
const bool &sequence, const long &seed) :
pgsObjectGen(seed), m_min(wxMin(min, max)), m_max(wxMax(min, max)),
m_range(m_max - m_min + 1), m_sequence(sequence)
{
m_randomizer = is_sequence()
? pgsRandomizer(pnew pgsSequentialIntGen(m_range, m_seed))
: pgsRandomizer(pnew pgsNormalIntGen(m_range, m_seed));
}
bool pgsIntegerGen::is_sequence() const
{
return m_sequence;
}
wxString pgsIntegerGen::random()
{
MAPM data = m_randomizer->random();
data = data + m_min;
wxASSERT(data >= m_min && data <= m_max);
return pgsMapm::pgs_mapm_str(data);
}
long pgsIntegerGen::random_long()
{
long result;
random().ToLong(&result);
return result;
}
pgsIntegerGen::~pgsIntegerGen()
{
}
pgsIntegerGen *pgsIntegerGen::clone()
{
return pnew pgsIntegerGen(*this);
}

View file

@ -0,0 +1,23 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/generators/pgsNumberGen.h"
pgsNumberGen::pgsNumberGen(const MAPM &range) :
m_range(range)
{
}
pgsNumberGen::~pgsNumberGen()
{
}

View file

@ -0,0 +1,23 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/generators/pgsObjectGen.h"
pgsObjectGen::pgsObjectGen(const long &seed) :
m_seed(seed == 0 ? 1 : seed)
{
}
pgsObjectGen::~pgsObjectGen()
{
}

View file

@ -0,0 +1,48 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/generators/pgsRealGen.h"
pgsRealGen::pgsRealGen(const MAPM &min, const MAPM &max,
const UCHAR &precision, const bool &sequence, const long &seed) :
pgsObjectGen(seed), m_min(wxMin(min, max)), m_max(wxMax(min, max)),
m_range(m_max - m_min), m_sequence(sequence)
{
m_pow = MAPM(10).pow(MAPM(precision));
m_int_max = pgsMapm::pgs_mapm_round(m_range * m_pow) + 1;
m_randomizer = is_sequence()
? pgsRandomizer(pnew pgsIntegerGen::pgsSequentialIntGen(m_int_max, m_seed))
: pgsRandomizer(pnew pgsIntegerGen::pgsNormalIntGen(m_int_max, m_seed));
}
bool pgsRealGen::is_sequence() const
{
return m_sequence;
}
wxString pgsRealGen::random()
{
MAPM data = m_randomizer->random() / m_pow;
data = data + m_min;
wxASSERT(data >= m_min && data <= m_max);
return pgsMapm::pgs_mapm_str(data);
}
pgsRealGen::~pgsRealGen()
{
}
pgsRealGen *pgsRealGen::clone()
{
return pnew pgsRealGen(*this);
}

View file

@ -0,0 +1,76 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/generators/pgsReferenceGen.h"
#include "pgscript/expressions/pgsExecute.h"
#include "pgscript/objects/pgsNumber.h"
#include "pgscript/objects/pgsRecord.h"
#include "pgscript/utilities/pgsThread.h"
pgsReferenceGen::pgsReferenceGen(pgsThread *app, const wxString &table,
const wxString &column, const bool &sequence, const long &seed) :
pgsObjectGen(seed), m_app(app), m_table(table), m_column(column),
m_sequence(sequence)
{
// We need an empty symbol table for calling pgsExecute.eval(...)
pgsVarMap vars;
// Count the number of lines in the table
pgsOperand result = pgsExecute(wxString() << wxT("SELECT count(*) FROM ")
<< m_table, 0, m_app).eval(vars);
wxASSERT(result->is_record());
wxString value = result->value();
if (!value.IsEmpty())
{
m_nb_rows = pgsMapm::pgs_str_mapm(result->number().value());
}
else
{
m_nb_rows = 0;
}
wxLogScriptVerbose(wxT("REFGEN: Number of rows in %s: %s"), m_table.c_str(),
pgsMapm::pgs_mapm_str(m_nb_rows).c_str());
// Create an integer generator with that number of lines
m_randomizer = pgsRandomizer(pnew pgsIntegerGen(0, m_nb_rows - 1,
is_sequence(), m_seed));
}
bool pgsReferenceGen::is_sequence() const
{
return m_sequence;
}
wxString pgsReferenceGen::random()
{
// We need an empty symbol table for calling pgsExecute.eval(...)
pgsVarMap vars;
// Choose one line
pgsOperand result = pgsExecute(wxString() << wxT("SELECT ") << m_column
<< wxT(" FROM ") << m_table << wxT(" LIMIT 1 OFFSET ")
<< m_randomizer->random(), 0, m_app).eval(vars);
wxASSERT(result->is_record());
// Return the result as a single value
return dynamic_cast<const pgsRecord &>(*result).get(0, 0)->value();
}
pgsReferenceGen::~pgsReferenceGen()
{
}
pgsReferenceGen *pgsReferenceGen::clone()
{
return pnew pgsReferenceGen(*this);
}

View file

@ -0,0 +1,309 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/generators/pgsRegexGen.h"
#include <wx/sstream.h>
#include <wx/regex.h>
#include <wx/xml/xml.h>
#include <wx/arrimpl.cpp>
WX_DEFINE_OBJARRAY(pgsVectorStringGen);
pgsRegexGen::pgsRegex::pgsRegex(const pgsVectorChar &characters,
const long &first, const long &second) :
m_characters(characters), m_first(wxMin(first, second)),
m_second(wxMax(first, second))
{
}
pgsRegexGen::pgsRegex::pgsRegex() :
m_characters(pgsVectorChar()), m_first(0), m_second(0)
{
}
pgsRegexGen::pgsRegex::~pgsRegex()
{
}
pgsRegexGen::pgsRegex *pgsRegexGen::pgsRegex::clone()
{
return pnew pgsRegexGen::pgsRegex(*this);
}
void pgsRegexGen::pgsRegex::set_characters(const pgsVectorChar &characters)
{
m_characters = characters;
}
void pgsRegexGen::pgsRegex::add_character(const wxChar &c)
{
m_characters.Add(c);
}
void pgsRegexGen::pgsRegex::set_first(const long &first)
{
m_first = first;
m_second = first;
}
void pgsRegexGen::pgsRegex::set_second(const long &second)
{
long first = m_first;
m_first = wxMin(first, second);
m_second = wxMax(first, second);
}
const pgsVectorChar &pgsRegexGen::pgsRegex::get_characters() const
{
return m_characters;
}
const long &pgsRegexGen::pgsRegex::get_first() const
{
return m_first;
}
const long &pgsRegexGen::pgsRegex::get_second() const
{
return m_second;
}
pgsRegexGen::pgsRegexGen(const wxString &regex, const long &seed) :
pgsObjectGen(seed), m_regex(regex), m_valid(true), m_string_gens(pgsVectorStringGen())
{
wxLogScriptVerbose(wxT("REGEXGEN: %s"), m_regex.c_str());
// Transform regular expression into XML structure
bool escape = false, first_regex = true, list = false;
wxString result = wxT("<regexpressions>\n");
size_t i = 0;
while (i < m_regex.Length())
{
if (escape)
{
if (list == true)
{
result.Append(espace_xml_char(m_regex[i]));
}
else
{
if (!first_regex)
result.Append(wxT(" </regex>\n"));
else
first_regex = false;
result.Append(wxT(" <regex>\n <characters>"));
result.Append(espace_xml_char(m_regex[i]));
result.Append(wxT("</characters>\n"));
}
escape = false;
}
else if (list == true && m_regex[i] == wxT('-'))
{
if ((i + 1) < m_regex.Length())
{
result.Append(char_range(m_regex[i - 1], m_regex[i + 1]));
}
}
else if (m_regex[i] == wxT('['))
{
if (!first_regex)
result.Append(wxT(" </regex>\n"));
else
first_regex = false;
result.Append(wxT(" <regex>\n <characters>"));
list = true;
}
else if (m_regex[i] == wxT(']'))
{
result.Append(wxT("</characters>\n"));
list = false;
}
else if (m_regex[i] == wxT('{'))
{
result.Append(wxT(" <range>"));
list = true;
}
else if (m_regex[i] == wxT('}'))
{
result.Append(wxT("</range>\n"));
list = false;
}
else if (m_regex[i] == wxT('\\'))
{
escape = true;
}
else
{
if (list == true)
{
result.Append(espace_xml_char(m_regex[i]));
}
else
{
if (!first_regex)
result.Append(wxT(" </regex>\n"));
else
first_regex = false;
result.Append(wxT(" <regex>\n <characters>"));
result.Append(espace_xml_char(m_regex[i]));
result.Append(wxT("</characters>\n"));
}
}
++i;
}
if (result != wxT("<regexpressions>\n"))
result.Append(wxT(" </regex>\n"));
result.Append(wxT("</regexpressions>\n"));
wxLogScriptVerbose(wxT("REGEXGEN: %s"), result.c_str());
// Load this XML structure with the wxXmlDocument from wxWidgets
wxStringInputStream input(result);
wxXmlDocument doc;
if (!doc.Load(input, wxT("UTF-8"), wxXMLDOC_KEEP_WHITESPACE_NODES))
{
m_valid = false;
}
else
{
// Start processing the XML file
if (doc.GetRoot()->GetName() != wxT("regexpressions"))
{
m_valid = false;
}
else
{
// Go through XML nodes
wxXmlNode *xml_regexpressions = doc.GetRoot()->GetChildren();
while (xml_regexpressions && m_valid)
{
if (xml_regexpressions->GetName() == wxT("regex"))
{
wxXmlNode *xml_regex = xml_regexpressions->GetChildren();
pgsRegex regex;
regex.set_first(1);
while (xml_regex && m_valid)
{
if (xml_regex->GetName() == wxT("characters"))
{
wxString content = xml_regex->GetNodeContent();
for (size_t i = 0; i < content.Length(); i++)
{
regex.add_character(content[i]);
}
}
else if (xml_regex->GetName() == wxT("range"))
{
wxString content = xml_regex->GetNodeContent();
wxRegEx ex(wxT("^([0-9]+)(,([0-9]+))?$"));
wxASSERT(ex.IsValid());
if (ex.Matches(content))
{
long min;
ex.GetMatch(content, 1).ToLong(&min);
regex.set_first(min);
wxString smax = ex.GetMatch(content, 3);
if (!smax.IsEmpty())
{
long max;
smax.ToLong(&max);
regex.set_second(max);
}
}
else
{
// m_valid = false;
}
}
xml_regex = xml_regex->GetNext();
}
m_string_gens.Add(pgsStringGen(regex.get_first(),
regex.get_second(), 1, seed,
regex.get_characters()));
}
xml_regexpressions = xml_regexpressions->GetNext();
}
}
}
}
wxString pgsRegexGen::random()
{
wxString result;
for (size_t i = 0; i < string_gens_size(); i++)
{
result.Append(m_string_gens.Item(i).random());
}
return result;
}
const pgsVectorStringGen &pgsRegexGen::string_gens() const
{
return m_string_gens;
}
size_t pgsRegexGen::string_gens_size() const
{
return m_string_gens.size();
}
const bool &pgsRegexGen::is_valid() const
{
return m_valid;
}
wxString pgsRegexGen::espace_xml_char(const wxChar &c)
{
if (c == wxT('<'))
return wxT("&lt;");
else if (c == wxT('&'))
return wxT("&amp;");
else if (c == wxT('>'))
return wxT("&gt;");
else if (c == wxT('"'))
return wxT("&quot;");
else if (c == wxT('\''))
return wxT("&apos;");
else return wxString(c);
}
wxString pgsRegexGen::char_range(const wxChar &b, const wxChar &c)
{
wxChar min = wxMin(b, c);
++min;
wxChar max = wxMax(b, c);
wxString result;
for (wxChar i = min; i < max; i++)
{
result.Append(espace_xml_char(i));
}
return result;
}
pgsRegexGen::~pgsRegexGen()
{
}
pgsRegexGen *pgsRegexGen::clone()
{
return pnew pgsRegexGen(*this);
}

View file

@ -0,0 +1,83 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/generators/pgsStringGen.h"
#include <wx/arrimpl.cpp>
WX_DEFINE_OBJARRAY(pgsVectorChar);
pgsStringGen::pgsStringGen(USHORT w_size_min, USHORT w_size_max,
const UCHAR &nb_words, const long &seed, pgsVectorChar characters) :
pgsObjectGen(seed), m_nb_words(nb_words), m_characters(characters)
{
init_characters(); // Initialize vector if it is empty
const USHORT w_size_aux = w_size_min;
w_size_min = wxMin(w_size_aux, w_size_max);
w_size_max = wxMax(w_size_aux, w_size_max);
size_t char_count = m_characters.GetCount();
m_w_size_randomizer = pgsRandomizer(pnew pgsIntegerGen(w_size_min,
w_size_max, false, seed));
m_letter_randomizer = pgsRandomizer(pnew pgsIntegerGen(0,
wx_static_cast(long, char_count) - 1, false, seed));
}
wxString pgsStringGen::random()
{
wxString str_result;
long w_size;
for (UCHAR i = 0; i < m_nb_words; i++)
{
w_size = m_w_size_randomizer->random_long();
for (long j = 0; j < w_size; j++)
{
str_result.Append(m_characters
.Item(m_letter_randomizer->random_long()), 1);
}
if (w_size > 0 && m_nb_words != (i + 1))
{
str_result.Append(wxT(' '), 1);
}
}
return str_result;
}
pgsStringGen::~pgsStringGen()
{
}
void pgsStringGen::init_characters()
{
if (m_characters.size() == 0)
{
for (char c = '0'; c <= '9'; c++)
{
m_characters.push_back(c);
}
for (char c = 'A'; c <= 'Z'; c++)
{
m_characters.push_back(c);
}
for (char c = 'a'; c <= 'z'; c++)
{
m_characters.push_back(c);
}
}
}
pgsStringGen *pgsStringGen::clone()
{
return pnew pgsStringGen(*this);
}

View file

@ -0,0 +1,52 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/generators/pgsTimeGen.h"
#include <string>
pgsTimeGen::pgsTimeGen(wxDateTime min, wxDateTime max, const bool &sequence,
const long &seed) :
pgsObjectGen(seed), m_min(min.IsEarlierThan(max) || min.IsEqualTo(max) ? min : max),
m_max(max.IsLaterThan(min) || max.IsEqualTo(min) ? max : min),
m_range(m_max.Subtract(m_min).GetSeconds()), m_sequence(sequence)
{
m_min.SetYear(1970); // We know this date is not a DST date
m_min.SetMonth(wxDateTime::Jan);
m_min.SetDay(1);
m_randomizer = pgsRandomizer(pnew pgsIntegerGen(0, std::string(m_range
.ToString().mb_str()).c_str(), is_sequence(), m_seed));
}
bool pgsTimeGen::is_sequence() const
{
return m_sequence;
}
wxString pgsTimeGen::random()
{
wxTimeSpan time_span(0, 0, m_randomizer->random_long(), 0);
wxDateTime aux_min(m_min);
aux_min.Add(time_span);
wxASSERT(aux_min.IsLaterThan(m_min) || aux_min.IsEqualTo(m_min));
wxASSERT(aux_min.IsEarlierThan(m_max) || aux_min.IsEqualTo(m_max));
return aux_min.FormatISOTime();
}
pgsTimeGen::~pgsTimeGen()
{
}
pgsTimeGen *pgsTimeGen::clone()
{
return pnew pgsTimeGen(*this);
}

2696
pgscript/lex.pgs.cc Normal file

File diff suppressed because it is too large Load diff

29
pgscript/module.mk Normal file
View file

@ -0,0 +1,29 @@
#######################################################################
#
# pgAdmin III - PostgreSQL Tools
#
# Copyright (C) 2002 - 2016, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
# module.mk - pgadmin/pgscript/ Makefile fragment
#
#######################################################################
pgadmin3_SOURCES += \
pgscript/pgsApplication.cpp \
pgscript/lex.pgs.cc \
pgscript/parser.tab.cc
EXTRA_DIST += \
pgscript/module.mk \
pgscript/parser.sh \
pgscript/pgsParser.yy \
pgscript/pgsScanner.ll \
pgscript/README
include pgscript/exceptions/module.mk
include pgscript/expressions/module.mk
include pgscript/generators/module.mk
include pgscript/objects/module.mk
include pgscript/statements/module.mk
include pgscript/utilities/module.mk

View file

@ -0,0 +1,21 @@
#######################################################################
#
# pgAdmin III - PostgreSQL Tools
#
# Copyright (C) 2002 - 2016, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
# module.mk - pgadmin/pgscript/objects/ Makefile fragment
#
#######################################################################
pgadmin3_SOURCES += \
pgscript/objects/pgsGenerator.cpp \
pgscript/objects/pgsNumber.cpp \
pgscript/objects/pgsRecord.cpp \
pgscript/objects/pgsString.cpp \
pgscript/objects/pgsVariable.cpp
EXTRA_DIST += \
pgscript/objects/module.mk

View file

@ -0,0 +1,154 @@
//////////////////////////////////////////////////////////////////////////
//
// 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/pgsGenerator.h"
#include "pgscript/objects/pgsNumber.h"
#include "pgscript/objects/pgsRecord.h"
#include "pgscript/objects/pgsString.h"
#include "pgscript/exceptions/pgsCastException.h"
pgsGenerator::pgsGenerator(const pgsTypes &generator_type,
pgsObjectGen *randomizer) :
pgsVariable(generator_type), m_randomizer(randomizer)
{
}
pgsGenerator::~pgsGenerator()
{
}
pgsVariable *pgsGenerator::clone() const
{
return pnew pgsGenerator(*this);
}
wxString pgsGenerator::value() const
{
return m_randomizer->random();
}
pgsOperand pgsGenerator::operand() const
{
switch (type())
{
case pgsTInt:
return pnew pgsNumber(value(), pgsInt);
case pgsTReal:
return pnew pgsNumber(value(), pgsReal);
default:
return pnew pgsString(value());
}
}
pgsOperand pgsGenerator::eval(pgsVarMap &vars) const
{
return this->clone();
}
pgsOperand pgsGenerator::pgs_plus(const pgsVariable &rhs) const
{
return *operand() + rhs;
}
pgsOperand pgsGenerator::pgs_minus(const pgsVariable &rhs) const
{
return *operand() - rhs;
}
pgsOperand pgsGenerator::pgs_times(const pgsVariable &rhs) const
{
return *operand() * rhs;
}
pgsOperand pgsGenerator::pgs_over(const pgsVariable &rhs) const
{
return *operand() / rhs;
}
pgsOperand pgsGenerator::pgs_modulo(const pgsVariable &rhs) const
{
return *operand() % rhs;
}
pgsOperand pgsGenerator::pgs_equal(const pgsVariable &rhs) const
{
return *operand() == rhs;
}
pgsOperand pgsGenerator::pgs_different(const pgsVariable &rhs) const
{
return *operand() != rhs;
}
pgsOperand pgsGenerator::pgs_greater(const pgsVariable &rhs) const
{
return *operand() > rhs;
}
pgsOperand pgsGenerator::pgs_lower(const pgsVariable &rhs) const
{
return *operand() < rhs;
}
pgsOperand pgsGenerator::pgs_lower_equal(const pgsVariable &rhs) const
{
return *operand() <= rhs;
}
pgsOperand pgsGenerator::pgs_greater_equal(const pgsVariable &rhs) const
{
return *operand() >= rhs;
}
pgsOperand pgsGenerator::pgs_not() const
{
return !(*operand());
}
bool pgsGenerator::pgs_is_true() const
{
return operand()->pgs_is_true();
}
pgsOperand pgsGenerator::pgs_almost_equal(const pgsVariable &rhs) const
{
return *operand() &= rhs;
}
pgsNumber pgsGenerator::number() const
{
wxString data = value().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 pgsGenerator::record() const
{
pgsRecord rec(1);
rec.insert(0, 0, operand());
return rec;
}
pgsString pgsGenerator::string() const
{
return pgsString(value());
}

View file

@ -0,0 +1,286 @@
//////////////////////////////////////////////////////////////////////////
//
// 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/pgsNumber.h"
#include <wx/regex.h>
#include "pgscript/objects/pgsRecord.h"
#include "pgscript/objects/pgsString.h"
#include "pgscript/exceptions/pgsArithmeticException.h"
#include "pgscript/exceptions/pgsCastException.h"
#define PGS_INTEGER_FORM_1 wxT("^[+-]?[0-9]+$")
#define PGS_REAL_FORM_1 wxT("^[+-]?[0-9]+[Ee][+-]?[0-9]+$")
#define PGS_REAL_FORM_2 wxT("^[+-]?[0-9]*[.][0-9]+([Ee][+-]?[0-9]+)?$")
#define PGS_REAL_FORM_3 wxT("^[+-]?[0-9]+[.][0-9]*([Ee][+-]?[0-9]+)?$")
pgsNumber::pgsNumber(const wxString &data, const bool &is_real) :
pgsVariable(!is_real ? pgsVariable::pgsTInt : pgsVariable::pgsTReal),
m_data(data.Strip(wxString::both))
{
wxASSERT(is_valid());
}
bool pgsNumber::is_valid() const
{
pgsTypes type = num_type(m_data);
return (type == pgsTInt) || (type == pgsTReal && is_real());
}
pgsNumber::~pgsNumber()
{
}
pgsNumber::pgsNumber(const pgsNumber &that) :
pgsVariable(that), m_data(that.m_data)
{
wxASSERT(is_valid());
}
pgsNumber &pgsNumber::operator =(const pgsNumber &that)
{
if (this != &that)
{
pgsVariable::operator=(that);
m_data = that.m_data;
}
wxASSERT(is_valid());
return (*this);
}
pgsVariable *pgsNumber::clone() const
{
return pnew pgsNumber(*this);
}
wxString pgsNumber::value() const
{
return m_data;
}
pgsOperand pgsNumber::eval(pgsVarMap &vars) const
{
return this->clone();
}
pgsVariable::pgsTypes pgsNumber::num_type(const wxString &num)
{
if (wxRegEx(PGS_INTEGER_FORM_1).Matches(num))
{
return pgsTInt;
}
else if (( wxRegEx(PGS_REAL_FORM_1).Matches(num)
|| wxRegEx(PGS_REAL_FORM_2).Matches(num)
|| wxRegEx(PGS_REAL_FORM_3).Matches(num)))
{
return pgsTReal;
}
else
{
return pgsTString;
}
}
pgsOperand pgsNumber::pgs_plus(const pgsVariable &rhs) const
{
if (rhs.is_number())
{
return pnew pgsNumber(pgsMapm::pgs_mapm_str(num(m_data)
+ num(rhs.value())), is_real() || rhs.is_real());
}
else
{
throw pgsArithmeticException(m_data, rhs.value());
}
}
pgsOperand pgsNumber::pgs_minus(const pgsVariable &rhs) const
{
if (rhs.is_number())
{
return pnew pgsNumber(pgsMapm::pgs_mapm_str(num(m_data)
- num(rhs.value())), is_real() || rhs.is_real());
}
else
{
throw pgsArithmeticException(m_data, rhs.value());
}
}
pgsOperand pgsNumber::pgs_times(const pgsVariable &rhs) const
{
if (rhs.is_number())
{
return pnew pgsNumber(pgsMapm::pgs_mapm_str(num(m_data)
* num(rhs.value())), is_real() || rhs.is_real());
}
else
{
throw pgsArithmeticException(m_data, rhs.value());
}
}
pgsOperand pgsNumber::pgs_over(const pgsVariable &rhs) const
{
if (rhs.is_number())
{
if (num(rhs.value()) != 0)
{
if (is_real() || rhs.is_real())
return pnew pgsNumber(pgsMapm::pgs_mapm_str(num(m_data)
/ num(rhs.value())), is_real() || rhs.is_real());
else
return pnew pgsNumber(pgsMapm::pgs_mapm_str(num(m_data)
.div(num(rhs.value()))), is_real() || rhs.is_real());
}
else
{
throw pgsArithmeticException(m_data, rhs.value());
}
}
else
{
throw pgsArithmeticException(m_data, rhs.value());
}
}
pgsOperand pgsNumber::pgs_modulo(const pgsVariable &rhs) const
{
if (rhs.is_number())
{
if (num(rhs.value()) != 0)
{
return pnew pgsNumber(pgsMapm::pgs_mapm_str(num(m_data)
% num(rhs.value())), is_real() || rhs.is_real());
}
else
{
throw pgsArithmeticException(m_data, rhs.value());
}
}
else
{
throw pgsArithmeticException(m_data, rhs.value());
}
}
pgsOperand pgsNumber::pgs_equal(const pgsVariable &rhs) const
{
if (rhs.is_number())
{
return pnew pgsNumber(num(m_data) == num(rhs.value())
? wxT("1") : wxT("0"));
}
else
{
throw pgsArithmeticException(m_data, rhs.value());
}
}
pgsOperand pgsNumber::pgs_different(const pgsVariable &rhs) const
{
if (rhs.is_number())
{
return pnew pgsNumber(num(m_data) != num(rhs.value())
? wxT("1") : wxT("0"));
}
else
{
throw pgsArithmeticException(m_data, rhs.value());
}
}
pgsOperand pgsNumber::pgs_greater(const pgsVariable &rhs) const
{
if (rhs.is_number())
{
return pnew pgsNumber(num(m_data) > num(rhs.value())
? wxT("1") : wxT("0"));
}
else
{
throw pgsArithmeticException(m_data, rhs.value());
}
}
pgsOperand pgsNumber::pgs_lower(const pgsVariable &rhs) const
{
if (rhs.is_number())
{
return pnew pgsNumber(num(m_data) < num(rhs.value())
? wxT("1") : wxT("0"));
}
else
{
throw pgsArithmeticException(m_data, rhs.value());
}
}
pgsOperand pgsNumber::pgs_lower_equal(const pgsVariable &rhs) const
{
if (rhs.is_number())
{
return pnew pgsNumber(num(m_data) <= num(rhs.value())
? wxT("1") : wxT("0"));
}
else
{
throw pgsArithmeticException(m_data, rhs.value());
}
}
pgsOperand pgsNumber::pgs_greater_equal(const pgsVariable &rhs) const
{
if (rhs.is_number())
{
return pnew pgsNumber(num(m_data) >= num(rhs.value())
? wxT("1") : wxT("0"));
}
else
{
throw pgsArithmeticException(m_data, rhs.value());
}
}
pgsOperand pgsNumber::pgs_not() const
{
return pnew pgsNumber(num(m_data) == 0 ? wxT("1") : wxT("0"));
}
bool pgsNumber::pgs_is_true() const
{
return (num(m_data) != 0 ? true : false);
}
pgsOperand pgsNumber::pgs_almost_equal(const pgsVariable &rhs) const
{
return pgs_equal(rhs);
}
pgsNumber pgsNumber::number() const
{
return pgsNumber(*this);
}
pgsRecord pgsNumber::record() const
{
pgsRecord rec(1);;
rec.insert(0, 0, this->clone());
return rec;
}
pgsString pgsNumber::string() const
{
return pgsString(m_data);
}

View file

@ -0,0 +1,509 @@
//////////////////////////////////////////////////////////////////////////
//
// 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/pgsRecord.h"
#include "pgscript/expressions/pgsEqual.h"
#include "pgscript/objects/pgsNumber.h"
#include "pgscript/objects/pgsString.h"
#include "pgscript/exceptions/pgsArithmeticException.h"
#include "pgscript/exceptions/pgsCastException.h"
#include <wx/arrimpl.cpp>
WX_DEFINE_OBJARRAY(pgsVectorRecordLine);
WX_DEFINE_OBJARRAY(pgsVectorRecord);
pgsRecord::pgsRecord(const USHORT &nb_columns) :
pgsVariable(pgsVariable::pgsTRecord)
{
m_columns.SetCount(nb_columns);
}
pgsRecord::~pgsRecord()
{
}
pgsVariable *pgsRecord::clone() const
{
return pnew pgsRecord(*this);
}
wxString pgsRecord::value() const
{
wxString data;
pgsVarMap vars;
// Go through each line and enclose it into braces
for (USHORT i = 0; i < count_lines(); i++)
{
data += wxT("(");
// Go through each column and separate them with commas
for (USHORT j = 0; j < count_columns(); j++)
{
wxString elm(m_record[i][j]->eval(vars)->value());
if (!m_record[i][j]->is_number())
{
elm.Replace(wxT("\\"), wxT("\\\\"));
elm.Replace(wxT("\""), wxT("\\\""));
elm = wxT("\"") + elm + wxT("\"");
}
data += elm + (j != count_columns() - 1 ? wxT(",") : wxT(""));
}
data += (i == count_lines() - 1) ? wxT(")") : wxT(")\n");
}
// Return the string representation of the record
return data;
}
pgsOperand pgsRecord::eval(pgsVarMap &vars) const
{
return this->clone();
}
USHORT pgsRecord::count_lines() const
{
return m_record.GetCount();
}
USHORT pgsRecord::count_columns() const
{
return m_columns.GetCount();
}
bool pgsRecord::insert(const USHORT &line, const USHORT &column,
pgsOperand value)
{
// Add lines to match the line number provided
for (USHORT i = count_lines(); i <= line; i++)
{
newline();
}
// Cannot insert if column is invalid
if (column >= count_columns())
{
return false;
}
// Insert the value at line.column
else
{
m_record[line][column] = value;
return true;
}
}
pgsOperand pgsRecord::get(const USHORT &line,
const USHORT &column) const
{
if (line < count_lines() && column < count_columns())
{
return m_record[line][column];
}
else
{
return pnew pgsString(wxT(""));
}
}
pgsOperand pgsRecord::get_line(const USHORT &line) const
{
if (line < count_lines())
{
pgsRecord *rec = pnew pgsRecord(count_columns());
rec->m_columns = this->m_columns;
rec->newline();
rec->m_record[0] = this->m_record[line];
return rec;
}
else
{
return pnew pgsRecord(0);
}
}
bool pgsRecord::set_column_name(const USHORT &column, wxString name)
{
// Column number must be valid
if (column >= count_columns())
{
return false;
}
// Column name must not exist
// Column name must not be empty
name = name.Strip(wxString::both).Lower();
if (m_columns.Index(name) != wxNOT_FOUND || name.IsEmpty())
{
return false;
}
// Set the column name
m_columns[column] = name;
return true;
}
USHORT pgsRecord::get_column(wxString name) const
{
name = name.Strip(wxString::both).Lower();
if (name.IsEmpty())
{
return count_columns();
}
for (USHORT i = 0; i < count_columns(); i++)
{
if (m_columns[i] == name)
return i;
}
return count_columns();
}
bool pgsRecord::remove_line(const USHORT &line)
{
if (line < count_lines())
{
m_record.RemoveAt(line);
return true;
}
return false;
}
bool pgsRecord::newline()
{
// Insert a line
m_record.Add(pgsVectorRecordLine());
// Initialize each column of the line with an empty string
for (USHORT i = 0; i < count_columns(); i++)
{
m_record.Last().Add(pnew pgsString(wxT("")));
}
return true;
}
bool pgsRecord::valid() const
{
return true;
}
bool pgsRecord::operator==(const pgsRecord &rhs) const
{
// Test the number of lines
if (this->count_lines() != rhs.count_lines())
{
return false;
}
return records_equal(*this, rhs, true);
}
bool pgsRecord::operator!=(const pgsRecord &rhs) const
{
return !(*this == rhs);
}
bool pgsRecord::operator<(const pgsRecord &rhs) const
{
// Test the number of lines
if (this->count_lines() >= rhs.count_lines())
{
return false;
}
return records_equal(*this, rhs, true);
}
bool pgsRecord::operator>(const pgsRecord &rhs) const
{
return (rhs < *this);
}
bool pgsRecord::operator<=(const pgsRecord &rhs) const
{
// Test the number of lines
if (this->count_lines() > rhs.count_lines())
{
return false;
}
return records_equal(*this, rhs, true);
}
bool pgsRecord::operator>=(const pgsRecord &rhs) const
{
return (rhs <= *this);
}
bool pgsRecord::almost_equal(const pgsRecord &rhs) const
{
// Test the number of lines
if (this->count_lines() != rhs.count_lines())
{
return false;
}
return records_equal(*this, rhs, false);
}
bool pgsRecord::records_equal(const pgsRecord &lhs, const pgsRecord &rhs,
bool case_sensitive) const
{
// Test the number of columns
if (lhs.count_columns() != rhs.count_columns())
{
return false;
}
// Test each line
wxArrayInt seen;
for (USHORT i = 0; i < lhs.count_lines(); i++)
{
bool result = false;
// Test if the line of lhs matches with an unseen line of rhs
for (USHORT j = 0; result == false && j < rhs.count_lines(); j++)
{
int k = wx_static_cast(int, j);
if (seen.Index(k) == wxNOT_FOUND
&& lines_equal(lhs.m_record[i], rhs.m_record[j],
case_sensitive))
{
result = true;
seen.push_back(k);
}
else
{
// This is not OK... Continue with the next element
continue;
}
}
if (result == false)
{
return false;
}
else
{
continue;
}
}
return true; // End of the test
}
bool pgsRecord::lines_equal(const pgsVectorRecordLine &lhs,
const pgsVectorRecordLine &rhs, bool case_sensitive) const
{
pgsVarMap vars;
// Both lines must have the same number of columns
if (lhs.GetCount() != rhs.GetCount())
{
return false;
}
// Test each element (column) of the line
for (USHORT j = 0; j < wx_static_cast(USHORT, lhs.GetCount()); j++)
{
// Test if the two elements are equal
pgsEqual test(lhs[j]->string().clone(), rhs[j]->string().clone(),
case_sensitive);
if (test.eval(vars)->value() == wxT("1"))
{
// lhs == rhs: continue
continue;
}
else
{
// lhs != rhs: lines are not equal
return false;
}
}
return true;
}
pgsOperand pgsRecord::pgs_plus(const pgsVariable &rhs) const
{
throw pgsArithmeticException(value(), rhs.value());
}
pgsOperand pgsRecord::pgs_minus(const pgsVariable &rhs) const
{
throw pgsArithmeticException(value(), rhs.value());
}
pgsOperand pgsRecord::pgs_times(const pgsVariable &rhs) const
{
throw pgsArithmeticException(value(), rhs.value());
}
pgsOperand pgsRecord::pgs_over(const pgsVariable &rhs) const
{
throw pgsArithmeticException(value(), rhs.value());
}
pgsOperand pgsRecord::pgs_modulo(const pgsVariable &rhs) const
{
throw pgsArithmeticException(value(), rhs.value());
}
pgsOperand pgsRecord::pgs_equal(const pgsVariable &rhs) const
{
if (rhs.is_record())
{
const pgsRecord &rhs_op = dynamic_cast<const pgsRecord &>(rhs);
return pnew pgsNumber(*this == rhs_op ? wxT("1") : wxT("0"));
}
else
{
throw pgsArithmeticException(value(), rhs.value());
}
}
pgsOperand pgsRecord::pgs_different(const pgsVariable &rhs) const
{
if (rhs.is_record())
{
const pgsRecord &rhs_op = dynamic_cast<const pgsRecord &>(rhs);
return pnew pgsNumber(*this != rhs_op ? wxT("1") : wxT("0"));
}
else
{
throw pgsArithmeticException(value(), rhs.value());
}
}
pgsOperand pgsRecord::pgs_greater(const pgsVariable &rhs) const
{
if (rhs.is_record())
{
const pgsRecord &rhs_op = dynamic_cast<const pgsRecord &>(rhs);
return pnew pgsNumber(*this > rhs_op ? wxT("1") : wxT("0"));
}
else
{
throw pgsArithmeticException(value(), rhs.value());
}
}
pgsOperand pgsRecord::pgs_lower(const pgsVariable &rhs) const
{
if (rhs.is_record())
{
const pgsRecord &rhs_op = dynamic_cast<const pgsRecord &>(rhs);
return pnew pgsNumber(*this < rhs_op ? wxT("1") : wxT("0"));
}
else
{
throw pgsArithmeticException(value(), rhs.value());
}
}
pgsOperand pgsRecord::pgs_lower_equal(const pgsVariable &rhs) const
{
if (rhs.is_record())
{
const pgsRecord &rhs_op = dynamic_cast<const pgsRecord &>(rhs);
return pnew pgsNumber(*this <= rhs_op ? wxT("1") : wxT("0"));
}
else
{
throw pgsArithmeticException(value(), rhs.value());
}
}
pgsOperand pgsRecord::pgs_greater_equal(const pgsVariable &rhs) const
{
if (rhs.is_record())
{
const pgsRecord &rhs_op = dynamic_cast<const pgsRecord &>(rhs);
return pnew pgsNumber(*this >= rhs_op ? wxT("1") : wxT("0"));
}
else
{
throw pgsArithmeticException(value(), rhs.value());
}
}
pgsOperand pgsRecord::pgs_not() const
{
if (pgs_is_true())
{
// A record with no line is false
return pnew pgsRecord(count_columns());
}
else
{
// A record with at least one line is true
pgsRecord *copy = pnew pgsRecord(*this);
copy->newline();
return copy; // Insert one line and return the record
}
}
bool pgsRecord::pgs_is_true() const
{
return (count_lines() > 0 ? true : false);
}
pgsOperand pgsRecord::pgs_almost_equal(const pgsVariable &rhs) const
{
if (rhs.is_record())
{
const pgsRecord &rhs_op = dynamic_cast<const pgsRecord &>(rhs);
return pnew pgsNumber(this->almost_equal(rhs_op) ? wxT("1") : wxT("0"));
}
else
{
throw pgsArithmeticException(value(), rhs.value());
}
}
pgsNumber pgsRecord::number() const
{
wxString data = value().Strip(wxString::both);
if (data.StartsWith(wxT("(")))
{
data = data.Mid(1);
}
if (data.EndsWith(wxT(")")))
{
data = data.Mid(0, data.Len() - 1);
}
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 pgsRecord::record() const
{
return pgsRecord(*this);
}
pgsString pgsRecord::string() const
{
return pgsString(value());
}

View file

@ -0,0 +1,290 @@
//////////////////////////////////////////////////////////////////////////
//
// 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);
}

View file

@ -0,0 +1,128 @@
//////////////////////////////////////////////////////////////////////////
//
// 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/pgsVariable.h"
pgsVariable::pgsVariable(const pgsTypes &type) :
pgsExpression(), m_type(type)
{
}
pgsVariable::~pgsVariable()
{
}
MAPM pgsVariable::num(const pgsOperand &var)
{
return pgsMapm::pgs_str_mapm(var->value());
}
MAPM pgsVariable::num(const wxString &var)
{
return pgsMapm::pgs_str_mapm(var);
}
bool pgsVariable::is_number() const
{
return is_integer() || is_real();
}
bool pgsVariable::is_integer() const
{
return m_type == pgsTInt;
}
bool pgsVariable::is_real() const
{
return m_type == pgsTReal;
}
bool pgsVariable::is_string() const
{
return m_type == pgsTString;
}
bool pgsVariable::is_record() const
{
return m_type == pgsTRecord;
}
const pgsVariable::pgsTypes &pgsVariable::type() const
{
return m_type;
}
pgsOperand operator+(const pgsVariable &lhs, const pgsVariable &rhs)
{
return lhs.pgs_plus(rhs);
}
pgsOperand operator-(const pgsVariable &lhs, const pgsVariable &rhs)
{
return lhs.pgs_minus(rhs);
}
pgsOperand operator*(const pgsVariable &lhs, const pgsVariable &rhs)
{
return lhs.pgs_times(rhs);
}
pgsOperand operator/(const pgsVariable &lhs, const pgsVariable &rhs)
{
return lhs.pgs_over(rhs);
}
pgsOperand operator%(const pgsVariable &lhs, const pgsVariable &rhs)
{
return lhs.pgs_modulo(rhs);
}
pgsOperand operator==(const pgsVariable &lhs, const pgsVariable &rhs)
{
return lhs.pgs_equal(rhs);
}
pgsOperand operator!=(const pgsVariable &lhs, const pgsVariable &rhs)
{
return lhs.pgs_different(rhs);
}
pgsOperand operator<(const pgsVariable &lhs, const pgsVariable &rhs)
{
return lhs.pgs_lower(rhs);
}
pgsOperand operator>(const pgsVariable &lhs, const pgsVariable &rhs)
{
return lhs.pgs_greater(rhs);
}
pgsOperand operator<=(const pgsVariable &lhs, const pgsVariable &rhs)
{
return lhs.pgs_lower_equal(rhs);
}
pgsOperand operator>=(const pgsVariable &lhs, const pgsVariable &rhs)
{
return lhs.pgs_greater_equal(rhs);
}
pgsOperand operator!(const pgsVariable &lhs)
{
return lhs.pgs_not();
}
pgsOperand operator&=(const pgsVariable &lhs, const pgsVariable &rhs)
{
return lhs.pgs_almost_equal(rhs);
}

80
pgscript/parser.sh Normal file
View file

@ -0,0 +1,80 @@
#!/bin/sh
#######################################################################
#
# pgAdmin III - PostgreSQL Tools
# Copyright (C) 2002 - 2016, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
# parser.sh - Runs Flex and Bison and processes the generated files
#
#######################################################################
# Directory containing pgScript includes (relative to the src directory)
INCLUDEDIR="include/pgscript"
# Directory containing pgScript sources (relative to the src directory)
SOURCEDIR="pgscript"
# Headers generated by Bison that need to be moved to ${INCLUDEDIR}
FILESTOMOVE=( "location.hh" "parser.tab.hh" "position.hh" "stack.hh" )
# Flex destination
LEXER="pgscript/lex.pgs.cc"
# A temporary file
AUX="pgscript/auxfile"
# Bison destination
PARSER="pgscript/parser.tab.cc"
#######################################################################
# Find the current directory
THISDIR=`dirname $0`
PREVDIR="$PWD"
# Go to the directory on top of the script directory
echo -n "cd ${THISDIR}/.. ... "
cd "${THISDIR}/.."
echo "done"
pwd
echo ""
# Generate Bison file
echo -n "+ Generating Bison output... "
bison -o"${PARSER}" "${SOURCEDIR}/pgsParser.yy"
echo "done"
# Generate Flex file
echo -n "+ Generating Flex output... "
flex -o"${LEXER}" "${SOURCEDIR}/pgsScanner.ll"
echo "done"
# Add pgAdmin3.h include at the beginning and change <FlexLexer.h> to
# "pgscript/FlexLexer.h" for the Flex output
echo -n "+ Processing Flex output... "
cat "${LEXER}" | awk 'BEGIN {print "#include \"pgAdmin3.h\"\n\n"}{print $0}' \
| sed -e 's/<FlexLexer\.h>/"pgscript\/FlexLexer\.h"/g' > "${AUX}"
mv -f "${AUX}" "${LEXER}"
echo "done"
# Add pgAdmin3.h include at the beginning and a pragma and change
# "parser.tab.hh" to "pgscript/parser.tab.hh" to the Bison output
echo -n "+ Processing Bison output... "
cat "${PARSER}" | awk 'BEGIN {print "#include \"pgAdmin3.h\"\n#if _MSC_VER > 1000\n#pragma warning(disable: 4800)\n#endif\n"}{print $0}' | \
sed -e 's/"parser.tab.hh"/"pgscript\/parser\.tab\.hh"/g' > "${AUX}"
sleep 1
mv -f "${AUX}" "${PARSER}"
echo "done"
# Move Bison include files to the include directory
echo + "Moving Bison header files... "
for file in ${FILESTOMOVE[@]}
do
echo " + mv ${SOURCEDIR}/${file} ${INCLUDEDIR}/${file}"
mv "${SOURCEDIR}/${file}" "${INCLUDEDIR}/${file}"
done
echo "... done"
# Go back to the previous directory
echo ""
echo -n "cd $PREVDIR ... "
cd "$PREVDIR"
echo "done"

2703
pgscript/parser.tab.cc Normal file

File diff suppressed because it is too large Load diff

215
pgscript/pgsApplication.cpp Normal file
View file

@ -0,0 +1,215 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/pgsApplication.h"
#include "db/pgConn.h"
#include "pgscript/expressions/pgsAssign.h"
#include "pgscript/expressions/pgsIdent.h"
#include "pgscript/objects/pgsString.h"
#include "pgscript/utilities/pgsThread.h"
pgsApplication::pgsApplication(const wxString &host, const wxString &database,
const wxString &user, const wxString &password, int port) :
m_mutex(1, 1), m_stream(1, 1), m_connection(pnew pgConn(host, wxEmptyString, wxEmptyString, database, user,
password, port)), m_defined_conn(true), m_thread(0), m_caller(0)
{
if (m_connection->GetStatus() != PGCONN_OK)
{
wxLogError(wxT("PGSCRIPT: Cannot connect to database %s:%d/%s with ")
wxT("credentials '%s'/'%s'"), host.c_str(), port, database.c_str(),
user.c_str(), password.c_str());
}
wxLogScript(wxT("Application created"));
}
pgsApplication::pgsApplication(pgConn *connection) :
m_mutex(1, 1), m_stream(1, 1), m_connection(connection),
m_defined_conn(false), m_thread(0), m_caller(0)
{
wxLogScript(wxT("Application created"));
}
pgsApplication::~pgsApplication()
{
if (m_defined_conn)
{
pdelete(m_connection);
}
wxLogScript(wxT("Application destroyed"));
}
bool pgsApplication::ParseFile(const wxString &file, pgsOutputStream &out,
wxMBConv *conv)
{
if (!IsRunning())
{
m_last_error_line = -1;
m_thread = new pgsThread(m_vars, m_mutex, m_connection,
file, out, *this, conv);
return RunThread();
}
else
{
return false;
}
}
bool pgsApplication::ParseString(const wxString &string,
pgsOutputStream &out)
{
if (!IsRunning())
{
m_last_error_line = -1;
m_thread = new pgsThread(m_vars, m_mutex, m_connection,
string, out, *this);
return RunThread();
}
else
{
return false;
}
}
bool pgsApplication::RunThread()
{
bool created = false;
if (m_thread != 0 && m_thread->Create() == wxTHREAD_NO_ERROR)
{
m_thread->SetPriority(WXTHREAD_MIN_PRIORITY);
if (m_thread->Run() == wxTHREAD_NO_ERROR)
{
created = true;
}
}
if (created)
{
wxLogScript(wxT("Running..."));
return true;
}
else
{
wxLogError(wxT("PGSCRIPT: Thread error"));
pdelete(m_thread);
return false;
}
}
bool pgsApplication::IsRunning()
{
if (m_mutex.TryWait() == wxSEMA_NO_ERROR)
{
m_mutex.Post();
return false;
}
else
{
return true;
}
}
void pgsApplication::Wait()
{
if (IsRunning())
{
wxLogScript(wxT("Waiting for pgScript"));
m_mutex.Wait();
m_mutex.Post();
}
}
void pgsApplication::Terminate()
{
if (IsRunning())
{
wxLogScript(wxT("Deleting pgScript"));
m_thread->Delete();
}
}
void pgsApplication::Complete()
{
// If last_error_line() == -1 then there was no error
// Else get the line number where the error occurred
m_last_error_line = m_thread->last_error_line();
#if !defined(PGSCLI)
if (m_caller != 0)
{
wxCommandEvent resultEvent(wxEVT_COMMAND_MENU_SELECTED, m_event_id);
#if wxCHECK_VERSION(2, 9, 0)
m_caller->GetEventHandler()->AddPendingEvent(resultEvent);
#else
m_caller->AddPendingEvent(resultEvent);
#endif
}
#endif // PGSCLI
wxLogScript(wxT("Execution completed"));
}
void pgsApplication::SetConnection(pgConn *conn)
{
if (m_defined_conn)
{
pdelete(m_connection);
m_defined_conn = false;
}
m_connection = conn;
}
void pgsApplication::ClearSymbols()
{
if (!IsRunning())
{
m_vars.clear();
}
}
#if !defined(PGSCLI)
void pgsApplication::SetCaller(wxWindow *caller, long event_id)
{
m_caller = caller;
m_event_id = event_id;
}
#endif // PGSCLI
bool pgsApplication::IsConnectionValid() const
{
return (m_connection->GetStatus() == PGCONN_OK);
}
void pgsApplication::LockOutput()
{
m_stream.Wait();
}
void pgsApplication::UnlockOutput()
{
m_stream.Post();
}
bool pgsApplication::errorOccurred() const
{
return (m_last_error_line != -1);
}
int pgsApplication::errorLine() const
{
return m_last_error_line;
}

1045
pgscript/pgsParser.yy Normal file

File diff suppressed because it is too large Load diff

421
pgscript/pgsScanner.ll Normal file
View file

@ -0,0 +1,421 @@
L [a-zA-Z_@#]
D [0-9]
E [e-eE-E][+-]?{D}+
%{ /*** C/C++ Declarations ***/
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgscript/pgScript.h"
#include "pgscript/parser.tab.hh"
#include "pgscript/utilities/pgsScanner.h"
/* Import the parser's token type into a local typedef */
typedef pgscript::pgsParser::token token;
typedef pgscript::pgsParser::token_type token_type;
/* Work around an incompatibility in flex (at least versions 2.5.31 through
* 2.5.33): it generates code that does not conform to C89. See Debian bug
* 333231 <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>. */
#undef yywrap
#define yywrap() 1
/* By default yylex returns int, we use token_type. Unfortunately yyterminate
* by default returns 0, which is not of token_type. */
#define yyterminate() return token::PGS_END
/* This disables inclusion of unistd.h, which is not available under Visual C++
* on Win32. The C++ scanner uses STL streams instead. */
#define YY_NO_UNISTD_H
%}
/*** Flex Declarations and Options ***/
/* Enable C++ scanner class generation */
%option c++
/* Change the name of the scanner class. Results in "pgsFlexLexer" */
%option prefix="pgs"
/* Case insensitive */
%option case-insensitive
/* The manual says "somewhat more optimized" */
%option batch
/* Prevent isatty warning in VC++ */
%option never-interactive
/* For using start conditions */
%option stack
/* No support for include files is planned */
%option noyywrap
/* The following paragraph suffices to track locations accurately. Each time
* yylex is invoked, the begin position is moved onto the end position. */
%{
#define YY_USER_ACTION yylloc->columns(yyleng);
%}
%x SC_COMMENT
%x SC_QUERY
%x SC_DOLLAR
%x SC_STRING
%% /*** Regular Expressions Part ***/
/* Code to place at the beginning of yylex() */
%{
// Reset location
yylloc->step();
%}
<INITIAL,SC_QUERY>"--".*$ { /* Ignore SQL comment */ }
<INITIAL>"/*" { comment_caller = INITIAL; BEGIN(SC_COMMENT); }
<SC_QUERY>"/*" { comment_caller = SC_QUERY; BEGIN(SC_COMMENT); }
<INITIAL>{
"WHILE" { return token::PGS_WHILE; }
"BREAK" { return token::PGS_BREAK; }
"RETURN" { return token::PGS_RETURN; }
"CONTINUE" { return token::PGS_CONTINUE; }
"IF" { return token::PGS_IF; }
"ELSE" { return token::PGS_ELSE; }
"WAITFOR" { return token::PGS_WAITFOR; }
"AS" { return token::PGS_AS; }
"ASSERT" { return token::PGS_ASSERT; }
"GO" { /* Ignore it */ }
"PRINT" { return token::PGS_PRINT; }
"COLUMNS" { return token::PGS_CNT_COLUMNS; }
"LINES" { return token::PGS_CNT_LINES; }
"TRIM" { return token::PGS_TRIM; }
"RMLINE" { return token::PGS_RM_LINE; }
"CAST" { return token::PGS_CAST; }
"RECORD" { return token::PGS_RECORD; }
"INTEGER" { return token::PGS_INTEGER; }
"REAL" { return token::PGS_REAL; }
"STRING" { return token::PGS_STRING; }
"REGEX" { return token::PGS_REGEX; }
"FILE" { return token::PGS_FILE; }
"DATE" { return token::PGS_DATE; }
"TIME" { return token::PGS_TIME; }
"DATETIME" { return token::PGS_DATE_TIME; }
"REFERENCE" { return token::PGS_REFERENCE; }
"SET"[ \t]+"@" { unput('@'); yylloc->end.columns(-1);
return token::PGS_SET_ASSIGN; }
"DECLARE"[ \t]+"@" { unput('@'); yylloc->end.columns(-1);
return token::PGS_DECLARE_ASSGN; }
"BEGIN" { /* Block opening */ return token::PGS_OPEN; }
"END" { /* Block closing */ return token::PGS_CLOSE; }
"@"({L}|{D})* { yylval->str = pnew wxString(yytext, m_conv);
return token::PGS_IDENTIFIER; }
{D}+ { yylval->str = pnew wxString(yytext, m_conv);
return token::PGS_VAL_INT; }
{D}*"."{D}+({E})? { yylval->str = pnew wxString(yytext, m_conv);
return token::PGS_VAL_REAL; }
{D}+{E} { yylval->str = pnew wxString(yytext, m_conv);
return token::PGS_VAL_REAL; }
{D}+"."{D}*({E})? { yylval->str = pnew wxString(yytext, m_conv);
return token::PGS_VAL_REAL; }
"AND" { return token::PGS_AND_OP; }
"OR" { return token::PGS_OR_OP; }
"<=" { return token::PGS_LE_OP; }
">=" { return token::PGS_GE_OP; }
"=" { return token::PGS_EQ_OP; }
"~=" { return token::PGS_AE_OP; }
"<>" { return token::PGS_NE_OP; }
";" { return wx_static_cast(token_type, ';'); }
("{"|"<%") { return wx_static_cast(token_type, '{'); }
("}"|"%>") { return wx_static_cast(token_type, '}'); }
":" { return wx_static_cast(token_type, ':'); }
"(" { return wx_static_cast(token_type, '('); }
")" { return wx_static_cast(token_type, ')'); }
("["|"<:") { return wx_static_cast(token_type, '['); }
("]"|":>") { return wx_static_cast(token_type, ']'); }
"." { return wx_static_cast(token_type, '.'); }
"," { return wx_static_cast(token_type, ','); }
"NOT" { return token::PGS_NOT_OP; }
"-" { return wx_static_cast(token_type, '-'); }
"+" { return wx_static_cast(token_type, '+'); }
"*" { return wx_static_cast(token_type, '*'); }
"/" { return wx_static_cast(token_type, '/'); }
"%" { return wx_static_cast(token_type, '%'); }
"<" { return wx_static_cast(token_type, '<'); }
">" { return wx_static_cast(token_type, '>'); }
"'" { string_caller = INITIAL; BEGIN(SC_STRING); }
"ABORT" { query += yytext; query_token = token::PGS_ABORT;
BEGIN(SC_QUERY); }
"ALTER" { query += yytext; query_token = token::PGS_ALTER;
BEGIN(SC_QUERY); }
"ANALYZE" { query += yytext; query_token = token::PGS_ANALYZE;
BEGIN(SC_QUERY); }
"BEGIN"[ \t]+"TRAN" { query += yytext; query_token = token::PGS_BEGIN;
BEGIN(SC_QUERY); }
"BEGIN"[ \t]+"WORK" { query += yytext; query_token = token::PGS_BEGIN;
BEGIN(SC_QUERY); }
"CHECKPOINT" { query += yytext; query_token = token::PGS_CHECKPOINT;
BEGIN(SC_QUERY); }
"CLOSE" { query += yytext; query_token = token::PGS_CLOSE_ST;
BEGIN(SC_QUERY); }
"CLUSTER" { query += yytext; query_token = token::PGS_CLUSTER;
BEGIN(SC_QUERY); }
"COMMENT" { query += yytext; query_token = token::PGS_COMMENT;
BEGIN(SC_QUERY); }
"COMMIT" { query += yytext; query_token = token::PGS_COMMIT;
BEGIN(SC_QUERY); }
"COPY" { query += yytext; query_token = token::PGS_COPY;
BEGIN(SC_QUERY); }
"CREATE" { query += yytext; query_token = token::PGS_CREATE;
BEGIN(SC_QUERY); }
"DEALLOCATE" { query += yytext; query_token = token::PGS_DEALLOCATE;
BEGIN(SC_QUERY); }
"DECLARE" { query += yytext; query_token = token::PGS_DECLARE;
BEGIN(SC_QUERY); }
"DELETE" { query += yytext; query_token = token::PGS_DELETE;
BEGIN(SC_QUERY); }
"DISCARD" { query += yytext; query_token = token::PGS_DISCARD;
BEGIN(SC_QUERY); }
"DROP" { query += yytext; query_token = token::PGS_DROP;
BEGIN(SC_QUERY); }
"END"[ \t]+"TRANS" { query += yytext; query_token = token::PGS_END_ST;
BEGIN(SC_QUERY); }
"END"[ \t]+"WORK" { query += yytext; query_token = token::PGS_END_ST;
BEGIN(SC_QUERY); }
"EXECUTE" { query += yytext; query_token = token::PGS_EXECUTE;
BEGIN(SC_QUERY); }
"EXPLAIN" { query += yytext; query_token = token::PGS_EXPLAIN;
BEGIN(SC_QUERY); }
"FETCH" { query += yytext; query_token = token::PGS_FETCH;
BEGIN(SC_QUERY); }
"GRANT" { query += yytext; query_token = token::PGS_GRANT;
BEGIN(SC_QUERY); }
"INSERT" { query += yytext; query_token = token::PGS_INSERT;
BEGIN(SC_QUERY); }
"LISTEN" { query += yytext; query_token = token::PGS_LISTEN;
BEGIN(SC_QUERY); }
"LOAD" { query += yytext; query_token = token::PGS_LOAD;
BEGIN(SC_QUERY); }
"LOCK" { query += yytext; query_token = token::PGS_LOCK;
BEGIN(SC_QUERY); }
"MOVE" { query += yytext; query_token = token::PGS_MOVE;
BEGIN(SC_QUERY); }
"NOTIFY" { query += yytext; query_token = token::PGS_NOTIFY;
BEGIN(SC_QUERY); }
"PREPARE" { query += yytext; query_token = token::PGS_PREPARE;
BEGIN(SC_QUERY); }
"REASSIGN" { query += yytext; query_token = token::PGS_REASSIGN;
BEGIN(SC_QUERY); }
"REINDEX" { query += yytext; query_token = token::PGS_REINDEX;
BEGIN(SC_QUERY); }
"RELEASE" { query += yytext; query_token = token::PGS_RELEASE;
BEGIN(SC_QUERY); }
"RESET" { query += yytext; query_token = token::PGS_RESET;
BEGIN(SC_QUERY); }
"REVOKE" { query += yytext; query_token = token::PGS_REVOKE;
BEGIN(SC_QUERY); }
"ROLLBACK" { query += yytext; query_token = token::PGS_ROLLBACK;
BEGIN(SC_QUERY); }
"SAVEPOINT" { query += yytext; query_token = token::PGS_SAVEPOINT;
BEGIN(SC_QUERY); }
"SELECT" { query += yytext; query_token = token::PGS_SELECT;
BEGIN(SC_QUERY); }
"SET" { query += yytext; query_token = token::PGS_SET;
BEGIN(SC_QUERY); }
"SHOW" { query += yytext; query_token = token::PGS_SHOW;
BEGIN(SC_QUERY); }
"START" { query += yytext; query_token = token::PGS_START;
BEGIN(SC_QUERY); }
"TRUNCATE" { query += yytext; query_token = token::PGS_TRUNCATE;
BEGIN(SC_QUERY); }
"UNLISTEN" { query += yytext; query_token = token::PGS_UNLISTEN;
BEGIN(SC_QUERY); }
"UPDATE" { query += yytext; query_token = token::PGS_UPDATE;
BEGIN(SC_QUERY); }
"VACUUM" { query += yytext; query_token = token::PGS_VACUUM;
BEGIN(SC_QUERY); }
"VALUES" { query += yytext; query_token = token::PGS_VALUES;
BEGIN(SC_QUERY); }
[ \t\v\f]+ { }
\r { yylloc->step(); }
\n { yylloc->lines(yyleng); yylloc->step(); }
. { return token::PGS_UNKNOWN; }
}
<SC_QUERY>{
"'" { query += yytext; string_caller = SC_QUERY; BEGIN(SC_STRING); }
\$({L}|{D})*\$ { query += yytext; dollar = yytext; BEGIN(SC_DOLLAR); }
";" { yylval->str = pnew wxString(query.c_str(), m_conv);
query.clear(); unput(';'); yylloc->end.columns(-1);
BEGIN(INITIAL); m_parent = 0; return query_token; }
"(" { ++m_parent; query += yytext; }
")" {
--m_parent;
if (m_parent == -1)
{
yylval->str = pnew wxString(query.c_str(), m_conv);
query.clear(); unput(')'); yylloc->end.columns(-1);
BEGIN(INITIAL); m_parent = 0; return query_token;
}
else
{
query += yytext;
}
}
\r { query += yytext; yylloc->step(); }
\n { query += yytext; yylloc->lines(yyleng); yylloc->step(); }
<<EOF>> { yylval->str = pnew wxString(query.c_str(), m_conv);
query.clear(); m_parent = 0; return query_token; }
. { yylloc->columns(columns(*yytext)); query += yytext; }
}
<SC_DOLLAR>{
\$({L}|{D})*\$ { query += yytext;
if (std::string(yytext) == dollar) BEGIN(SC_QUERY); }
\r { query += yytext; yylloc->step(); }
\n { query += yytext; yylloc->lines(yyleng); yylloc->step(); }
<<EOF>> { query += yytext; yylval->str = pnew wxString(query.c_str(), m_conv);
query.clear(); m_parent = 0; return query_token; }
. { yylloc->columns(columns(*yytext)); query += yytext; }
}
<SC_COMMENT>{
"*/" { BEGIN(comment_caller); }
\r { yylloc->step(); }
\n { yylloc->lines(yyleng); yylloc->step(); }
. { yylloc->columns(columns(*yytext)); }
}
<SC_STRING>{
"''" {
if (string_caller == SC_QUERY)
query += yytext;
else
str += "'";
}
\\. {
if (string_caller == SC_QUERY)
query += yytext;
else
str += *(yytext + 1);
yylloc->columns(columns(*(yytext + 1)));
}
"'" {
if (string_caller == SC_QUERY)
{
query += yytext;
BEGIN(string_caller);
}
else
{
yylval->str = pnew wxString(str.c_str(), m_conv);
str.clear();
BEGIN(string_caller);
return token::PGS_VAL_STR;
}
}
\r {
if (string_caller == SC_QUERY)
query += yytext;
else
str += yytext;
yylloc->step();
}
\n {
if (string_caller == SC_QUERY)
query += yytext;
else
str += yytext;
yylloc->lines(yyleng); yylloc->step();
}
<<EOF>> {
if (string_caller == SC_QUERY)
{
query += yytext; yylval->str = pnew wxString(query.c_str(), m_conv);
query.clear(); m_parent = 0; return query_token;
}
else
{
yylval->str = pnew wxString(str.c_str(), m_conv);
str.clear();
BEGIN(string_caller);
return token::PGS_VAL_STR;
}
}
. {
if (string_caller == SC_QUERY)
query += yytext;
else
str += yytext;
yylloc->columns(columns(*yytext));
}
}
%% /*** Additional Code ***/
namespace pgscript
{
pgsScanner::pgsScanner(wxMBConv & conv, std::istream * in, std::ostream * out) :
pgsFlexLexer(in, out), m_parent(0), m_conv(conv)
{
}
pgsScanner::~pgsScanner()
{
}
void pgsScanner::set_debug(bool b)
{
yy_flex_debug = b;
}
int pgsScanner::columns(const char & c)
{
if ((c & 0xF0) == 0xF0) // 4 bytes
return -3;
else if ((c & 0xE0) == 0xE0) // 3 bytes
return -2;
else if ((c & 0xC0) == 0xC0) // 2 bytes
return -1;
else return 0;
}
}
/* This implementation of pgsFlexLexer::yylex() is required to fill the
* vtable of the class pgsFlexLexer. We define the scanner's main yylex
* function via YY_DECL to reside in the pgsScanner class instead. */
#ifdef yylex
#undef yylex
#endif
int pgsFlexLexer::yylex()
{
return 0;
}

View file

@ -0,0 +1,27 @@
#######################################################################
#
# pgAdmin III - PostgreSQL Tools
#
# Copyright (C) 2002 - 2016, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
# module.mk - pgadmin/pgscript/statements/ Makefile fragment
#
#######################################################################
pgadmin3_SOURCES += \
pgscript/statements/pgsAssertStmt.cpp \
pgscript/statements/pgsBreakStmt.cpp \
pgscript/statements/pgsContinueStmt.cpp \
pgscript/statements/pgsDeclareRecordStmt.cpp \
pgscript/statements/pgsExpressionStmt.cpp \
pgscript/statements/pgsIfStmt.cpp \
pgscript/statements/pgsPrintStmt.cpp \
pgscript/statements/pgsProgram.cpp \
pgscript/statements/pgsStmt.cpp \
pgscript/statements/pgsStmtList.cpp \
pgscript/statements/pgsWhileStmt.cpp
EXTRA_DIST += \
pgscript/statements/module.mk

View file

@ -0,0 +1,34 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/statements/pgsAssertStmt.h"
#include "pgscript/exceptions/pgsAssertException.h"
pgsAssertStmt::pgsAssertStmt(const pgsExpression *cond, pgsThread *app) :
pgsStmt(app), m_cond(cond)
{
}
pgsAssertStmt::~pgsAssertStmt()
{
pdelete(m_cond);
}
void pgsAssertStmt::eval(pgsVarMap &vars) const
{
pgsOperand result = m_cond->eval(vars);
if (!result->pgs_is_true())
{
throw pgsAssertException(m_cond->value());
}
}

View file

@ -0,0 +1,30 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/statements/pgsBreakStmt.h"
#include "pgscript/exceptions/pgsBreakException.h"
pgsBreakStmt::pgsBreakStmt(pgsThread *app) :
pgsStmt(app)
{
}
pgsBreakStmt::~pgsBreakStmt()
{
}
void pgsBreakStmt::eval(pgsVarMap &vars) const
{
throw pgsBreakException();
}

View file

@ -0,0 +1,30 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/statements/pgsContinueStmt.h"
#include "pgscript/exceptions/pgsContinueException.h"
pgsContinueStmt::pgsContinueStmt(pgsThread *app) :
pgsStmt(app)
{
}
pgsContinueStmt::~pgsContinueStmt()
{
}
void pgsContinueStmt::eval(pgsVarMap &vars) const
{
throw pgsContinueException();
}

View file

@ -0,0 +1,36 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/statements/pgsDeclareRecordStmt.h"
#include "pgscript/objects/pgsRecord.h"
pgsDeclareRecordStmt::pgsDeclareRecordStmt(const wxString &rec,
const wxArrayString &columns, pgsThread *app) :
pgsStmt(app), m_rec(rec), m_columns(columns)
{
}
pgsDeclareRecordStmt::~pgsDeclareRecordStmt()
{
}
void pgsDeclareRecordStmt::eval(pgsVarMap &vars) const
{
pgsRecord *rec = pnew pgsRecord(m_columns.size());
for (size_t i = 0; i < m_columns.GetCount(); i++)
{
rec->set_column_name(i, m_columns.Item(i));
}
vars[m_rec] = rec;
}

View file

@ -0,0 +1,28 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/statements/pgsExpressionStmt.h"
pgsExpressionStmt::pgsExpressionStmt(const pgsExpression *var, pgsThread *app) :
pgsStmt(app), m_var(var)
{
}
pgsExpressionStmt::~pgsExpressionStmt()
{
pdelete(m_var)
}
void pgsExpressionStmt::eval(pgsVarMap &vars) const
{
m_var->eval(vars);
}

View file

@ -0,0 +1,39 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/statements/pgsIfStmt.h"
pgsIfStmt::pgsIfStmt(const pgsExpression *cond, const pgsStmt *stmt_list_if,
const pgsStmt *stmt_list_else, pgsThread *app) :
pgsStmt(app), m_cond(cond), m_stmt_list_if(stmt_list_if),
m_stmt_list_else(stmt_list_else)
{
}
pgsIfStmt::~pgsIfStmt()
{
pdelete(m_cond);
pdelete(m_stmt_list_if);
pdelete(m_stmt_list_else);
}
void pgsIfStmt::eval(pgsVarMap &vars) const
{
if (m_cond->eval(vars)->pgs_is_true())
{
m_stmt_list_if->eval(vars);
}
else
{
m_stmt_list_else->eval(vars);
}
}

View file

@ -0,0 +1,56 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/statements/pgsPrintStmt.h"
#include "pgscript/exceptions/pgsException.h"
#include "pgscript/utilities/pgsThread.h"
#include "pgscript/utilities/pgsUtilities.h"
pgsPrintStmt::pgsPrintStmt(const pgsExpression *var, pgsOutputStream &cout,
pgsThread *app) :
pgsStmt(app), m_var(var), m_cout(cout)
{
}
pgsPrintStmt::~pgsPrintStmt()
{
pdelete(m_var);
}
void pgsPrintStmt::eval(pgsVarMap &vars) const
{
if (m_app != 0)
{
m_app->LockOutput();
}
try
{
m_cout << PGSOUTPGSCRIPT << wx_static_cast(const wxString,
m_var->eval(vars)->value()) << wxT("\n");
}
catch (const pgsException &)
{
if (m_app != 0)
{
m_app->UnlockOutput();
}
throw;
}
if (m_app != 0)
{
m_app->UnlockOutput();
}
}

View file

@ -0,0 +1,63 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/statements/pgsProgram.h"
#include "pgscript/exceptions/pgsException.h"
#include "pgscript/statements/pgsStmtList.h"
pgsProgram::pgsProgram(pgsVarMap &vars) :
m_vars(vars)
{
}
pgsProgram::~pgsProgram()
{
}
void pgsProgram::dump()
{
dump(m_vars);
}
void pgsProgram::dump(const pgsVarMap &vars)
{
pgsVarMap::const_iterator it;
for (it = vars.begin(); it != vars.end(); it++)
{
wxLogMessage(wxString() << it->first << wxT(" -> ")
<< it->second->value());
}
}
void pgsProgram::eval(pgsStmtList *stmt_list)
{
wxLogScript(wxT("Entering program"));
try
{
stmt_list->eval(m_vars);
}
catch (const pgsException &)
{
}
catch (const std::exception &)
{
}
pgsStmtList::m_exception_thrown = false;
wxLogScript(wxT("Leaving program"));
}

View file

@ -0,0 +1,33 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/statements/pgsStmt.h"
pgsStmt::pgsStmt(pgsThread *app) :
m_line(0), m_app(app)
{
}
pgsStmt::~pgsStmt()
{
}
void pgsStmt::set_position(int line)
{
m_line = line;
}
int pgsStmt::line() const
{
return m_line;
}

View file

@ -0,0 +1,115 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/statements/pgsStmtList.h"
#include <typeinfo>
#include "pgscript/exceptions/pgsBreakException.h"
#include "pgscript/exceptions/pgsContinueException.h"
#include "pgscript/exceptions/pgsInterruptException.h"
#include "pgscript/utilities/pgsThread.h"
#include "pgscript/utilities/pgsUtilities.h"
#include <wx/listimpl.cpp>
WX_DEFINE_LIST(pgsListStmt);
bool pgsStmtList::m_exception_thrown = false;
pgsStmtList::pgsStmtList(pgsOutputStream &cout, pgsThread *app) :
pgsStmt(app), m_cout(cout)
{
}
pgsStmtList::~pgsStmtList()
{
pgsListStmt::iterator it;
for (it = m_stmt_list.begin(); it != m_stmt_list.end(); it++)
{
pdelete(*it);
}
}
void pgsStmtList::eval(pgsVarMap &vars) const
{
pgsListStmt::const_iterator it;
for (it = m_stmt_list.begin(); it != m_stmt_list.end(); it++)
{
pgsStmt *current = *it;
try
{
current->eval(vars);
if (m_app != 0 && m_app->TestDestroy())
throw pgsInterruptException();
}
catch (const pgsException &e)
{
if (!m_exception_thrown && (typeid(e) != typeid(pgsBreakException))
&& (typeid(e) != typeid(pgsContinueException)))
{
if (m_app != 0)
{
m_app->LockOutput();
m_app->last_error_line(current->line());
}
m_cout << wx_static_cast(const wxString, e.message())
<< wxT(" on line ") << current->line() << wxT("\n");
m_exception_thrown = true;
if (m_app != 0)
{
m_app->UnlockOutput();
}
}
throw;
}
catch (const std::exception &e)
{
if (!m_exception_thrown)
{
if (m_app != 0)
{
m_app->LockOutput();
m_app->last_error_line(current->line());
}
m_cout << PGSOUTERROR << _("Unknown exception:\n")
<< wx_static_cast(const wxString,
wxString(e.what(), wxConvUTF8));
m_exception_thrown = true;
if (m_app != 0)
{
m_app->UnlockOutput();
}
}
throw;
}
if (m_app != 0)
{
m_app->Yield();
}
}
}
void pgsStmtList::insert_front(pgsStmt *stmt)
{
m_stmt_list.push_front(stmt);
}
void pgsStmtList::insert_back(pgsStmt *stmt)
{
m_stmt_list.push_back(stmt);
}

View file

@ -0,0 +1,56 @@
//////////////////////////////////////////////////////////////////////////
//
// pgScript - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#include "pgscript/statements/pgsWhileStmt.h"
#include "pgscript/exceptions/pgsBreakException.h"
#include "pgscript/exceptions/pgsContinueException.h"
#include "pgscript/exceptions/pgsInterruptException.h"
#include "pgscript/utilities/pgsThread.h"
pgsWhileStmt::pgsWhileStmt(const pgsExpression *cond, const pgsStmt *stmt_list,
pgsThread *app) :
pgsStmt(app), m_cond(cond), m_stmt_list(stmt_list)
{
}
pgsWhileStmt::~pgsWhileStmt()
{
pdelete(m_cond);
pdelete(m_stmt_list);
}
void pgsWhileStmt::eval(pgsVarMap &vars) const
{
loop:
if (m_cond->eval(vars)->pgs_is_true())
{
try
{
m_stmt_list->eval(vars);
}
catch (const pgsBreakException &)
{
goto end;
}
catch (const pgsContinueException &)
{
}
if (m_app != 0 && m_app->TestDestroy())
throw pgsInterruptException();
goto loop;
}
end:
;
}

View file

@ -0,0 +1,154 @@
/*
* M_APM - mapm5sin.c
*
* Copyright (C) 1999 - 2007 Michael C. Ring
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted. Permission to distribute
* the modified code is granted. Modifications are to be distributed by
* using the file 'license.txt' as a template to modify the file header.
* 'license.txt' is available in the official MAPM distribution.
*
* This software is provided "as is" without express or implied warranty.
*/
/*
*
* This file contains the functions that implement the sin (5x)
* and cos (4x) multiple angle relations
*
*/
#include "pgAdmin3.h"
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
/****************************************************************************/
void M_5x_sin(M_APM r, int places, M_APM x)
{
M_APM tmp8, tmp9;
tmp8 = M_get_stack_var();
tmp9 = M_get_stack_var();
m_apm_multiply(tmp9, x, MM_5x_125R); /* 1 / (5*5*5) */
M_raw_sin(tmp8, (places + 6), tmp9);
M_5x_do_it(tmp9, (places + 4), tmp8);
M_5x_do_it(tmp8, (places + 4), tmp9);
M_5x_do_it(r, places, tmp8);
M_restore_stack(2);
}
/****************************************************************************/
void M_4x_cos(M_APM r, int places, M_APM x)
{
M_APM tmp8, tmp9;
tmp8 = M_get_stack_var();
tmp9 = M_get_stack_var();
/*
* if |x| >= 1.0 use multiple angle identity 4 times
* if |x| < 1.0 use multiple angle identity 3 times
*/
if (x->m_apm_exponent > 0)
{
m_apm_multiply(tmp9, x, MM_5x_256R); /* 1 / (4*4*4*4) */
M_raw_cos(tmp8, (places + 8), tmp9);
M_4x_do_it(tmp9, (places + 8), tmp8);
M_4x_do_it(tmp8, (places + 6), tmp9);
M_4x_do_it(tmp9, (places + 4), tmp8);
M_4x_do_it(r, places, tmp9);
}
else
{
m_apm_multiply(tmp9, x, MM_5x_64R); /* 1 / (4*4*4) */
M_raw_cos(tmp8, (places + 6), tmp9);
M_4x_do_it(tmp9, (places + 4), tmp8);
M_4x_do_it(tmp8, (places + 4), tmp9);
M_4x_do_it(r, places, tmp8);
}
M_restore_stack(2);
}
/****************************************************************************/
/*
* calculate the multiple angle identity for sin (5x)
*
* sin (5x) == 16 * sin^5 (x) - 20 * sin^3 (x) + 5 * sin(x)
*/
void M_5x_do_it(M_APM rr, int places, M_APM xx)
{
M_APM tmp0, tmp1, t2, t3, t5;
tmp0 = M_get_stack_var();
tmp1 = M_get_stack_var();
t2 = M_get_stack_var();
t3 = M_get_stack_var();
t5 = M_get_stack_var();
m_apm_multiply(tmp1, xx, xx);
m_apm_round(t2, (places + 4), tmp1); /* x ^ 2 */
m_apm_multiply(tmp1, t2, xx);
m_apm_round(t3, (places + 4), tmp1); /* x ^ 3 */
m_apm_multiply(t5, t2, t3); /* x ^ 5 */
m_apm_multiply(tmp0, xx, MM_Five);
m_apm_multiply(tmp1, t5, MM_5x_Sixteen);
m_apm_add(t2, tmp0, tmp1);
m_apm_multiply(tmp1, t3, MM_5x_Twenty);
m_apm_subtract(tmp0, t2, tmp1);
m_apm_round(rr, places, tmp0);
M_restore_stack(5);
}
/****************************************************************************/
/*
* calculate the multiple angle identity for cos (4x)
*
* cos (4x) == 8 * [ cos^4 (x) - cos^2 (x) ] + 1
*/
void M_4x_do_it(M_APM rr, int places, M_APM xx)
{
M_APM tmp0, tmp1, t2, t4;
tmp0 = M_get_stack_var();
tmp1 = M_get_stack_var();
t2 = M_get_stack_var();
t4 = M_get_stack_var();
m_apm_multiply(tmp1, xx, xx);
m_apm_round(t2, (places + 4), tmp1); /* x ^ 2 */
m_apm_multiply(t4, t2, t2); /* x ^ 4 */
m_apm_subtract(tmp0, t4, t2);
m_apm_multiply(tmp1, tmp0, MM_5x_Eight);
m_apm_add(tmp0, MM_One, tmp1);
m_apm_round(rr, places, tmp0);
M_restore_stack(4);
}
/****************************************************************************/
/*
* compute r = sqrt(1 - a ^ 2).
*/
void M_cos_to_sin(M_APM r, int places, M_APM a)
{
M_APM tmp1, tmp2;
tmp1 = M_get_stack_var();
tmp2 = M_get_stack_var();
m_apm_multiply(tmp1, a, a);
m_apm_subtract(tmp2, MM_One, tmp1);
m_apm_sqrt(r, places, tmp2);
M_restore_stack(2);
}
/****************************************************************************/

View file

@ -0,0 +1,329 @@
/*
* M_APM - mapm_add.c
*
* Copyright (C) 1999 - 2007 Michael C. Ring
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted. Permission to distribute
* the modified code is granted. Modifications are to be distributed by
* using the file 'license.txt' as a template to modify the file header.
* 'license.txt' is available in the official MAPM distribution.
*
* This software is provided "as is" without express or implied warranty.
*/
/*
*
* This file contains the functions that implement the sin (5x)
* and cos (4x) multiple angle relations
*
*/
#include "pgAdmin3.h"
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
static M_APM M_work1 = NULL;
static M_APM M_work2 = NULL;
static int M_add_firsttime = TRUE;
/****************************************************************************/
void M_free_all_add()
{
if (M_add_firsttime == FALSE)
{
m_apm_free(M_work1);
m_apm_free(M_work2);
M_add_firsttime = TRUE;
}
}
/****************************************************************************/
void m_apm_add(M_APM r, M_APM a, M_APM b)
{
int j, carry, sign, aexp, bexp, adigits, bdigits;
if (M_add_firsttime)
{
M_add_firsttime = FALSE;
M_work1 = m_apm_init();
M_work2 = m_apm_init();
}
if (a->m_apm_sign == 0)
{
m_apm_copy(r, b);
return;
}
if (b->m_apm_sign == 0)
{
m_apm_copy(r, a);
return;
}
if (a->m_apm_sign == 1 && b->m_apm_sign == -1)
{
b->m_apm_sign = 1;
m_apm_subtract(r, a, b);
b->m_apm_sign = -1;
return;
}
if (a->m_apm_sign == -1 && b->m_apm_sign == 1)
{
a->m_apm_sign = 1;
m_apm_subtract(r, b, a);
a->m_apm_sign = -1;
return;
}
sign = a->m_apm_sign; /* signs are the same, result will be same */
aexp = a->m_apm_exponent;
bexp = b->m_apm_exponent;
m_apm_copy(M_work1, a);
m_apm_copy(M_work2, b);
/*
* scale by at least 1 factor of 10 in case the MSB carrys
*/
if (aexp == bexp)
{
M_apm_scale(M_work1, 2); /* shift 2 digits == 1 byte for efficiency */
M_apm_scale(M_work2, 2);
}
else
{
if (aexp > bexp)
{
M_apm_scale(M_work1, 2);
M_apm_scale(M_work2, (aexp + 2 - bexp));
}
else /* aexp < bexp */
{
M_apm_scale(M_work2, 2);
M_apm_scale(M_work1, (bexp + 2 - aexp));
}
}
adigits = M_work1->m_apm_datalength;
bdigits = M_work2->m_apm_datalength;
if (adigits >= bdigits)
{
m_apm_copy(r, M_work1);
j = (bdigits + 1) >> 1;
carry = 0;
while (TRUE)
{
j--;
r->m_apm_data[j] += carry + M_work2->m_apm_data[j];
if (r->m_apm_data[j] >= 100)
{
r->m_apm_data[j] -= 100;
carry = 1;
}
else
carry = 0;
if (j == 0)
break;
}
}
else
{
m_apm_copy(r, M_work2);
j = (adigits + 1) >> 1;
carry = 0;
while (TRUE)
{
j--;
r->m_apm_data[j] += carry + M_work1->m_apm_data[j];
if (r->m_apm_data[j] >= 100)
{
r->m_apm_data[j] -= 100;
carry = 1;
}
else
carry = 0;
if (j == 0)
break;
}
}
r->m_apm_sign = sign;
M_apm_normalize(r);
}
/****************************************************************************/
void m_apm_subtract(M_APM r, M_APM a, M_APM b)
{
int itmp, j, flag, icompare, sign, aexp, bexp,
borrow, adigits, bdigits;
if (M_add_firsttime)
{
M_add_firsttime = FALSE;
M_work1 = m_apm_init();
M_work2 = m_apm_init();
}
if (b->m_apm_sign == 0)
{
m_apm_copy(r, a);
return;
}
if (a->m_apm_sign == 0)
{
m_apm_copy(r, b);
r->m_apm_sign = -(r->m_apm_sign);
return;
}
if (a->m_apm_sign == 1 && b->m_apm_sign == -1)
{
b->m_apm_sign = 1;
m_apm_add(r, a, b);
b->m_apm_sign = -1;
return;
}
if (a->m_apm_sign == -1 && b->m_apm_sign == 1)
{
b->m_apm_sign = -1;
m_apm_add(r, a, b);
b->m_apm_sign = 1;
return;
}
/* now, the signs are the same */
/* make a positive working copy */
m_apm_absolute_value(M_work1, a);
m_apm_absolute_value(M_work2, b);
/* are they the same?? if so, the result is zero */
if ((icompare = m_apm_compare(M_work1, M_work2)) == 0)
{
M_set_to_zero(r);
return;
}
if (icompare == 1) /* |a| > |b| (do A-B) */
{
flag = TRUE;
sign = a->m_apm_sign;
}
else /* |b| > |a| (do B-A) */
{
flag = FALSE;
sign = -(a->m_apm_sign);
}
aexp = M_work1->m_apm_exponent;
bexp = M_work2->m_apm_exponent;
if (aexp > bexp)
M_apm_scale(M_work2, (aexp - bexp));
if (aexp < bexp)
M_apm_scale(M_work1, (bexp - aexp));
adigits = M_work1->m_apm_datalength;
bdigits = M_work2->m_apm_datalength;
if (adigits > bdigits)
M_apm_pad(M_work2, adigits);
if (adigits < bdigits)
M_apm_pad(M_work1, bdigits);
if (flag) /* perform A-B, M_work1 - M_work2 */
{
m_apm_copy(r, M_work1);
j = (r->m_apm_datalength + 1) >> 1;
borrow = 0;
while (TRUE)
{
j--;
itmp = (int)r->m_apm_data[j] - ((int)M_work2->m_apm_data[j] + borrow);
if (itmp >= 0)
{
r->m_apm_data[j] = (UCHAR)itmp;
borrow = 0;
}
else
{
r->m_apm_data[j] = (UCHAR)(100 + itmp);
borrow = 1;
}
if (j == 0)
break;
}
}
else /* perform B-A, M_work2 - M_work1 */
{
m_apm_copy(r, M_work2);
j = (r->m_apm_datalength + 1) >> 1;
borrow = 0;
while (TRUE)
{
j--;
itmp = (int)r->m_apm_data[j] - ((int)M_work1->m_apm_data[j] + borrow);
if (itmp >= 0)
{
r->m_apm_data[j] = (UCHAR)itmp;
borrow = 0;
}
else
{
r->m_apm_data[j] = (UCHAR)(100 + itmp);
borrow = 1;
}
if (j == 0)
break;
}
}
r->m_apm_sign = sign;
M_apm_normalize(r);
}
/****************************************************************************/
#ifdef __cplusplus
MAPM operator+(const MAPM &a, const MAPM &b)
{
MAPM ret;
m_apm_add(ret.val(), a.cval(), b.cval());
return ret;
}
MAPM operator-(const MAPM &a, const MAPM &b)
{
MAPM ret;
m_apm_subtract(ret.val(), a.cval(), b.cval());
return ret;
}
#endif

View file

@ -0,0 +1,161 @@
/*
* M_APM - mapm_cpi.c
*
* Copyright (C) 1999 - 2007 Michael C. Ring
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted. Permission to distribute
* the modified code is granted. Modifications are to be distributed by
* using the file 'license.txt' as a template to modify the file header.
* 'license.txt' is available in the official MAPM distribution.
*
* This software is provided "as is" without express or implied warranty.
*/
/*
*
* This file contains the PI related functions.
*
*/
#include "pgAdmin3.h"
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
/****************************************************************************/
/*
* check if our local copy of PI is precise enough
* for our purpose. if not, calculate PI so it's
* as precise as desired, accurate to 'places' decimal
* places.
*/
void M_check_PI_places(int places)
{
int dplaces;
dplaces = places + 2;
if (dplaces > MM_lc_PI_digits)
{
MM_lc_PI_digits = dplaces + 2;
/* compute PI using the AGM (see right below) */
M_calculate_PI_AGM(MM_lc_PI, (dplaces + 5));
m_apm_multiply(MM_lc_HALF_PI, MM_0_5, MM_lc_PI);
m_apm_multiply(MM_lc_2_PI, MM_Two, MM_lc_PI);
}
}
/****************************************************************************/
/*
* Calculate PI using the AGM (Arithmetic-Geometric Mean)
*
* Init : A0 = 1
* B0 = 1 / sqrt(2)
* Sum = 1
*
* Iterate: n = 1...
*
*
* A = 0.5 * [ A + B ]
* n n-1 n-1
*
*
* B = sqrt [ A * B ]
* n n-1 n-1
*
*
*
* C = 0.5 * [ A - B ]
* n n-1 n-1
*
*
* 2 n+1
* Sum = Sum - C * 2
* n
*
*
* At the end when C is 'small enough' :
* n
*
* 2
* PI = 4 * A / Sum
* n+1
*
* -OR-
*
* 2
* PI = ( A + B ) / Sum
* n n
*
*/
void M_calculate_PI_AGM(M_APM outv, int places)
{
M_APM tmp1, tmp2, a0, b0, c0, a1, b1, sum, pow_2;
int dplaces, nn;
tmp1 = M_get_stack_var();
tmp2 = M_get_stack_var();
a0 = M_get_stack_var();
b0 = M_get_stack_var();
c0 = M_get_stack_var();
a1 = M_get_stack_var();
b1 = M_get_stack_var();
sum = M_get_stack_var();
pow_2 = M_get_stack_var();
dplaces = places + 16;
m_apm_copy(a0, MM_One);
m_apm_copy(sum, MM_One);
m_apm_copy(pow_2, MM_Four);
m_apm_sqrt(b0, dplaces, MM_0_5); /* sqrt(0.5) */
while (TRUE)
{
m_apm_add(tmp1, a0, b0);
m_apm_multiply(a1, MM_0_5, tmp1);
m_apm_multiply(tmp1, a0, b0);
m_apm_sqrt(b1, dplaces, tmp1);
m_apm_subtract(tmp1, a0, b0);
m_apm_multiply(c0, MM_0_5, tmp1);
/*
* the net 'PI' calculated from this iteration will
* be accurate to ~4 X the value of (c0)'s exponent.
* this was determined experimentally.
*/
nn = -4 * c0->m_apm_exponent;
m_apm_multiply(tmp1, c0, c0);
m_apm_multiply(tmp2, tmp1, pow_2);
m_apm_subtract(tmp1, sum, tmp2);
m_apm_round(sum, dplaces, tmp1);
if (nn >= dplaces)
break;
m_apm_copy(a0, a1);
m_apm_copy(b0, b1);
m_apm_multiply(tmp1, pow_2, MM_Two);
m_apm_copy(pow_2, tmp1);
}
m_apm_add(tmp1, a1, b1);
m_apm_multiply(tmp2, tmp1, tmp1);
m_apm_divide(tmp1, dplaces, tmp2, sum);
m_apm_round(outv, places, tmp1);
M_restore_stack(9);
}
/****************************************************************************/

View file

@ -0,0 +1,300 @@
/*
* M_APM - mapm_div.c
*
* Copyright (C) 1999 - 2007 Michael C. Ring
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted. Permission to distribute
* the modified code is granted. Modifications are to be distributed by
* using the file 'license.txt' as a template to modify the file header.
* 'license.txt' is available in the official MAPM distribution.
*
* This software is provided "as is" without express or implied warranty.
*/
/*
*
* This file contains the basic division functions
*
*/
#include "pgAdmin3.h"
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
static M_APM M_div_worka;
static M_APM M_div_workb;
static M_APM M_div_tmp7;
static M_APM M_div_tmp8;
static M_APM M_div_tmp9;
static int M_div_firsttime = TRUE;
/****************************************************************************/
void M_free_all_div()
{
if (M_div_firsttime == FALSE)
{
m_apm_free(M_div_worka);
m_apm_free(M_div_workb);
m_apm_free(M_div_tmp7);
m_apm_free(M_div_tmp8);
m_apm_free(M_div_tmp9);
M_div_firsttime = TRUE;
}
}
/****************************************************************************/
void m_apm_integer_div_rem(M_APM qq, M_APM rr, M_APM aa, M_APM bb)
{
m_apm_integer_divide(qq, aa, bb);
m_apm_multiply(M_div_tmp7, qq, bb);
m_apm_subtract(rr, aa, M_div_tmp7);
}
/****************************************************************************/
void m_apm_integer_divide(M_APM rr, M_APM aa, M_APM bb)
{
/*
* we must use this divide function since the
* faster divide function using the reciprocal
* will round the result (possibly changing
* nnm.999999... --> nn(m+1).0000 which would
* invalidate the 'integer_divide' goal).
*/
M_apm_sdivide(rr, 4, aa, bb);
if (rr->m_apm_exponent <= 0) /* result is 0 */
{
M_set_to_zero(rr);
}
else
{
if (rr->m_apm_datalength > rr->m_apm_exponent)
{
rr->m_apm_datalength = rr->m_apm_exponent;
M_apm_normalize(rr);
}
}
}
/****************************************************************************/
void M_apm_sdivide(M_APM r, int places, M_APM a, M_APM b)
{
int j, k, m, b0, sign, nexp, indexr, icompare, iterations;
long trial_numer;
void *vp;
if (M_div_firsttime)
{
M_div_firsttime = FALSE;
M_div_worka = m_apm_init();
M_div_workb = m_apm_init();
M_div_tmp7 = m_apm_init();
M_div_tmp8 = m_apm_init();
M_div_tmp9 = m_apm_init();
}
sign = a->m_apm_sign * b->m_apm_sign;
if (sign == 0) /* one number is zero, result is zero */
{
if (b->m_apm_sign == 0)
{
M_apm_log_error_msg(M_APM_RETURN, "\'M_apm_sdivide\', Divide by 0");
}
M_set_to_zero(r);
return;
}
/*
* Knuth step D1. Since base = 100, base / 2 = 50.
* (also make the working copies positive)
*/
if (b->m_apm_data[0] >= 50)
{
m_apm_absolute_value(M_div_worka, a);
m_apm_absolute_value(M_div_workb, b);
}
else /* 'normal' step D1 */
{
k = 100 / (b->m_apm_data[0] + 1);
m_apm_set_long(M_div_tmp9, (long)k);
m_apm_multiply(M_div_worka, M_div_tmp9, a);
m_apm_multiply(M_div_workb, M_div_tmp9, b);
M_div_worka->m_apm_sign = 1;
M_div_workb->m_apm_sign = 1;
}
/* setup trial denominator for step D3 */
b0 = 100 * (int)M_div_workb->m_apm_data[0];
if (M_div_workb->m_apm_datalength >= 3)
b0 += M_div_workb->m_apm_data[1];
nexp = M_div_worka->m_apm_exponent - M_div_workb->m_apm_exponent;
if (nexp > 0)
iterations = nexp + places + 1;
else
iterations = places + 1;
k = (iterations + 1) >> 1; /* required size of result, in bytes */
if (k > r->m_apm_malloclength)
{
if ((vp = MAPM_REALLOC(r->m_apm_data, (k + 32))) == NULL)
{
/* fatal, this does not return */
M_apm_log_error_msg(M_APM_FATAL, "\'M_apm_sdivide\', Out of memory");
}
r->m_apm_malloclength = k + 28;
r->m_apm_data = (UCHAR *)vp;
}
/* clear the exponent in the working copies */
M_div_worka->m_apm_exponent = 0;
M_div_workb->m_apm_exponent = 0;
/* if numbers are equal, ratio == 1.00000... */
if ((icompare = m_apm_compare(M_div_worka, M_div_workb)) == 0)
{
iterations = 1;
r->m_apm_data[0] = 10;
nexp++;
}
else /* ratio not 1, do the real division */
{
if (icompare == 1) /* numerator > denominator */
{
nexp++; /* to adjust the final exponent */
M_div_worka->m_apm_exponent += 1; /* multiply numerator by 10 */
}
else /* numerator < denominator */
{
M_div_worka->m_apm_exponent += 2; /* multiply numerator by 100 */
}
indexr = 0;
m = 0;
while (TRUE)
{
/*
* Knuth step D3. Only use the 3rd -> 6th digits if the number
* actually has that many digits.
*/
trial_numer = 10000L * (long)M_div_worka->m_apm_data[0];
if (M_div_worka->m_apm_datalength >= 5)
{
trial_numer += 100 * M_div_worka->m_apm_data[1]
+ M_div_worka->m_apm_data[2];
}
else
{
if (M_div_worka->m_apm_datalength >= 3)
trial_numer += 100 * M_div_worka->m_apm_data[1];
}
j = (int)(trial_numer / b0);
/*
* Since the library 'normalizes' all the results, we need
* to look at the exponent of the number to decide if we
* have a lead in 0n or 00.
*/
if ((k = 2 - M_div_worka->m_apm_exponent) > 0)
{
while (TRUE)
{
j /= 10;
if (--k == 0)
break;
}
}
if (j == 100) /* qhat == base ?? */
j = 99; /* if so, decrease by 1 */
m_apm_set_long(M_div_tmp8, (long)j);
m_apm_multiply(M_div_tmp7, M_div_tmp8, M_div_workb);
/*
* Compare our q-hat (j) against the desired number.
* j is either correct, 1 too large, or 2 too large
* per Theorem B on pg 272 of Art of Compter Programming,
* Volume 2, 3rd Edition.
*
* The above statement is only true if using the 2 leading
* digits of the numerator and the leading digit of the
* denominator. Since we are using the (3) leading digits
* of the numerator and the (2) leading digits of the
* denominator, we eliminate the case where our q-hat is
* 2 too large, (and q-hat being 1 too large is quite remote).
*/
if (m_apm_compare(M_div_tmp7, M_div_worka) == 1)
{
j--;
m_apm_subtract(M_div_tmp8, M_div_tmp7, M_div_workb);
m_apm_copy(M_div_tmp7, M_div_tmp8);
}
/*
* Since we know q-hat is correct, step D6 is unnecessary.
*
* Store q-hat, step D5. Since D6 is unnecessary, we can
* do D5 before D4 and decide if we are done.
*/
r->m_apm_data[indexr++] = (UCHAR)j; /* j == 'qhat' */
m += 2;
if (m >= iterations)
break;
/* step D4 */
m_apm_subtract(M_div_tmp9, M_div_worka, M_div_tmp7);
/*
* if the subtraction yields zero, the division is exact
* and we are done early.
*/
if (M_div_tmp9->m_apm_sign == 0)
{
iterations = m;
break;
}
/* multiply by 100 and re-save */
M_div_tmp9->m_apm_exponent += 2;
m_apm_copy(M_div_worka, M_div_tmp9);
}
}
r->m_apm_sign = sign;
r->m_apm_exponent = nexp;
r->m_apm_datalength = iterations;
M_apm_normalize(r);
}
/****************************************************************************/

View file

@ -0,0 +1,294 @@
/*
* M_APM - mapm_exp.c
*
* Copyright (C) 1999 - 2007 Michael C. Ring
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted. Permission to distribute
* the modified code is granted. Modifications are to be distributed by
* using the file 'license.txt' as a template to modify the file header.
* 'license.txt' is available in the official MAPM distribution.
*
* This software is provided "as is" without express or implied warranty.
*/
/*
*
* This file contains the EXP function.
*
*/
#include "pgAdmin3.h"
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
static M_APM MM_exp_log2R;
static M_APM MM_exp_512R;
static int MM_firsttime1 = TRUE;
/****************************************************************************/
void M_free_all_exp()
{
if (MM_firsttime1 == FALSE)
{
m_apm_free(MM_exp_log2R);
m_apm_free(MM_exp_512R);
MM_firsttime1 = TRUE;
}
}
/****************************************************************************/
void m_apm_exp(M_APM r, int places, M_APM x)
{
M_APM tmp7, tmp8, tmp9;
int dplaces, nn, ii;
if (MM_firsttime1)
{
MM_firsttime1 = FALSE;
MM_exp_log2R = m_apm_init();
MM_exp_512R = m_apm_init();
m_apm_set_string(MM_exp_log2R, "1.44269504089"); /* ~ 1 / log(2) */
m_apm_set_string(MM_exp_512R, "1.953125E-3"); /* 1 / 512 */
}
tmp7 = M_get_stack_var();
tmp8 = M_get_stack_var();
tmp9 = M_get_stack_var();
if (x->m_apm_sign == 0) /* if input == 0, return '1' */
{
m_apm_copy(r, MM_One);
M_restore_stack(3);
return;
}
if (x->m_apm_exponent <= -3) /* already small enough so call _raw directly */
{
M_raw_exp(tmp9, (places + 6), x);
m_apm_round(r, places, tmp9);
M_restore_stack(3);
return;
}
/*
From David H. Bailey's MPFUN Fortran package :
exp (t) = (1 + r + r^2 / 2! + r^3 / 3! + r^4 / 4! ...) ^ q * 2 ^ n
where q = 256, r = t' / q, t' = t - n Log(2) and where n is chosen so
that -0.5 Log(2) < t' <= 0.5 Log(2). Reducing t mod Log(2) and
dividing by 256 insures that -0.001 < r <= 0.001, which accelerates
convergence in the above series.
I use q = 512 and also limit how small 'r' can become. The 'r' used
here is limited in magnitude from 1.95E-4 < |r| < 1.35E-3. Forcing
'r' into a narrow range keeps the algorithm 'well behaved'.
( the range is [0.1 / 512] to [log(2) / 512] )
*/
if (M_exp_compute_nn(&nn, tmp7, x) != 0)
{
M_apm_log_error_msg(M_APM_RETURN,
"\'m_apm_exp\', Input too large, Overflow");
M_set_to_zero(r);
M_restore_stack(3);
return;
}
dplaces = places + 8;
/* check to make sure our log(2) is accurate enough */
M_check_log_places(dplaces);
m_apm_multiply(tmp8, tmp7, MM_lc_log2);
m_apm_subtract(tmp7, x, tmp8);
/*
* guarantee that |tmp7| is between 0.1 and 0.9999999....
* (in practice, the upper limit only reaches log(2), 0.693... )
*/
while (TRUE)
{
if (tmp7->m_apm_sign != 0)
{
if (tmp7->m_apm_exponent == 0)
break;
}
if (tmp7->m_apm_sign >= 0)
{
nn++;
m_apm_subtract(tmp8, tmp7, MM_lc_log2);
m_apm_copy(tmp7, tmp8);
}
else
{
nn--;
m_apm_add(tmp8, tmp7, MM_lc_log2);
m_apm_copy(tmp7, tmp8);
}
}
m_apm_multiply(tmp9, tmp7, MM_exp_512R);
/* perform the series expansion ... */
M_raw_exp(tmp8, dplaces, tmp9);
/*
* raise result to the 512 power
*
* note : x ^ 512 = (((x ^ 2) ^ 2) ^ 2) ... 9 times
*/
ii = 9;
while (TRUE)
{
m_apm_multiply(tmp9, tmp8, tmp8);
m_apm_round(tmp8, dplaces, tmp9);
if (--ii == 0)
break;
}
/* now compute 2 ^ N */
m_apm_integer_pow(tmp7, dplaces, MM_Two, nn);
m_apm_multiply(tmp9, tmp7, tmp8);
m_apm_round(r, places, tmp9);
M_restore_stack(3); /* restore the 3 locals we used here */
}
/****************************************************************************/
/*
compute int *n = round_to_nearest_int(a / log(2))
M_APM b = MAPM version of *n
returns 0: OK
-1, 1: failure
*/
int M_exp_compute_nn(int *n, M_APM b, M_APM a)
{
M_APM tmp0, tmp1;
void *vp;
char *cp, sbuf[48];
int kk;
*n = 0;
vp = NULL;
cp = sbuf;
tmp0 = M_get_stack_var();
tmp1 = M_get_stack_var();
/* find 'n' and convert it to a normal C int */
/* we just need an approx 1/log(2) for this calculation */
m_apm_multiply(tmp1, a, MM_exp_log2R);
/* round to the nearest int */
if (tmp1->m_apm_sign >= 0)
{
m_apm_add(tmp0, tmp1, MM_0_5);
m_apm_floor(tmp1, tmp0);
}
else
{
m_apm_subtract(tmp0, tmp1, MM_0_5);
m_apm_ceil(tmp1, tmp0);
}
kk = tmp1->m_apm_exponent;
if (kk >= 42)
{
if ((vp = (void *)MAPM_MALLOC((kk + 16) * sizeof(char))) == NULL)
{
/* fatal, this does not return */
M_apm_log_error_msg(M_APM_FATAL, "\'M_exp_compute_nn\', Out of memory");
}
cp = (char *)vp;
}
m_apm_to_integer_string(cp, tmp1);
*n = atoi(cp);
m_apm_set_long(b, (long)(*n));
kk = m_apm_compare(b, tmp1);
if (vp != NULL)
MAPM_FREE(vp);
M_restore_stack(2);
return(kk);
}
/****************************************************************************/
/*
calculate the exponential function using the following series :
x^2 x^3 x^4 x^5
exp(x) == 1 + x + --- + --- + --- + --- ...
2! 3! 4! 5!
*/
void M_raw_exp(M_APM rr, int places, M_APM xx)
{
M_APM tmp0, digit, term;
int tolerance, local_precision, prev_exp;
long m1;
tmp0 = M_get_stack_var();
term = M_get_stack_var();
digit = M_get_stack_var();
local_precision = places + 8;
tolerance = -(places + 4);
prev_exp = 0;
m_apm_add(rr, MM_One, xx);
m_apm_copy(term, xx);
m1 = 2L;
while (TRUE)
{
m_apm_set_long(digit, m1);
m_apm_multiply(tmp0, term, xx);
m_apm_divide(term, local_precision, tmp0, digit);
m_apm_add(tmp0, rr, term);
m_apm_copy(rr, tmp0);
if ((term->m_apm_exponent < tolerance) || (term->m_apm_sign == 0))
break;
if (m1 != 2L)
{
local_precision = local_precision + term->m_apm_exponent - prev_exp;
if (local_precision < 20)
local_precision = 20;
}
prev_exp = term->m_apm_exponent;
m1++;
}
M_restore_stack(3); /* restore the 3 locals we used here */
}
/****************************************************************************/

View file

@ -0,0 +1,55 @@
/*
* M_APM - mapm_fam.c
*
* Copyright (C) 1999 - 2007 Michael C. Ring
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted. Permission to distribute
* the modified code is granted. Modifications are to be distributed by
* using the file 'license.txt' as a template to modify the file header.
* 'license.txt' is available in the official MAPM distribution.
*
* This software is provided "as is" without express or implied warranty.
*/
/*
*
* This file contains the free all memory and similiar functions.
*
*/
#include "pgAdmin3.h"
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
/****************************************************************************/
void m_apm_free_all_mem()
{
M_free_all_add(); /* call each module which has statically declared data */
M_free_all_div();
M_free_all_exp();
#ifndef NO_FFT_MULTIPLY
M_free_all_fft();
#endif
M_free_all_pow();
M_free_all_rnd();
M_free_all_set();
M_free_all_cnst();
M_free_all_fmul();
M_free_all_stck();
M_free_all_util();
}
/****************************************************************************/
void m_apm_trim_mem_usage()
{
m_apm_free_all_mem();
m_apm_free(m_apm_init());
}
/****************************************************************************/

View file

@ -0,0 +1,953 @@
/*
* M_APM - mapm_fft.c
*
* This FFT (Fast Fourier Transform) is from Takuya OOURA
*
* Copyright(C) 1996-1999 Takuya OOURA
* email: ooura@mmm.t.u-tokyo.ac.jp
*
* See full FFT documentation below ... (MCR)
*
* This software is provided "as is" without express or implied warranty.
*/
/*
*
* This file contains the FFT based FAST MULTIPLICATION function
* as well as its support functions.
*
*/
#include "pgAdmin3.h"
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
#ifndef MM_PI_2
#define MM_PI_2 1.570796326794896619231321691639751442098584699687
#endif
#ifndef WR5000 /* cos(MM_PI_2*0.5000) */
#define WR5000 0.707106781186547524400844362104849039284835937688
#endif
#ifndef RDFT_LOOP_DIV /* control of the RDFT's speed & tolerance */
#define RDFT_LOOP_DIV 64
#endif
extern void M_fast_mul_fft(UCHAR *, UCHAR *, UCHAR *, int);
extern void M_rdft(int, int, double *);
extern void M_bitrv2(int, double *);
extern void M_cftfsub(int, double *);
extern void M_cftbsub(int, double *);
extern void M_rftfsub(int, double *);
extern void M_rftbsub(int, double *);
extern void M_cft1st(int, double *);
extern void M_cftmdl(int, int, double *);
static double *M_aa_array, *M_bb_array;
static int M_size = -1;
static char *M_fft_error_msg = (char *)"\'M_fast_mul_fft\', Out of memory";
/****************************************************************************/
void M_free_all_fft()
{
if (M_size > 0)
{
MAPM_FREE(M_aa_array);
MAPM_FREE(M_bb_array);
M_size = -1;
}
}
/****************************************************************************/
/*
* multiply 'uu' by 'vv' with nbytes each
* yielding a 2*nbytes result in 'ww'.
* each byte contains a base 100 'digit',
* i.e.: range from 0-99.
*
* MSB LSB
*
* uu,vv [0] [1] [2] ... [N-1]
* ww [0] [1] [2] ... [2N-1]
*/
void M_fast_mul_fft(UCHAR *ww, UCHAR *uu, UCHAR *vv, int nbytes)
{
int mflag, i, j, nn2, nn;
double carry, nnr, dtemp, *a, *b;
UCHAR *w0;
unsigned long ul;
if (M_size < 0) /* if first time in, setup working arrays */
{
if (M_get_sizeof_int() == 2) /* if still using 16 bit compilers */
M_size = 516;
else
M_size = 8200;
M_aa_array = (double *)MAPM_MALLOC(M_size * sizeof(double));
M_bb_array = (double *)MAPM_MALLOC(M_size * sizeof(double));
if ((M_aa_array == NULL) || (M_bb_array == NULL))
{
/* fatal, this does not return */
M_apm_log_error_msg(M_APM_FATAL, M_fft_error_msg);
}
}
nn = nbytes;
nn2 = nbytes >> 1;
if (nn > M_size)
{
mflag = TRUE;
a = (double *)MAPM_MALLOC((nn + 8) * sizeof(double));
b = (double *)MAPM_MALLOC((nn + 8) * sizeof(double));
if ((a == NULL) || (b == NULL))
{
/* fatal, this does not return */
M_apm_log_error_msg(M_APM_FATAL, M_fft_error_msg);
}
}
else
{
mflag = FALSE;
a = M_aa_array;
b = M_bb_array;
}
/*
* convert normal base 100 MAPM numbers to base 10000
* for the FFT operation.
*/
i = 0;
for (j = 0; j < nn2; j++)
{
a[j] = (double)((int)uu[i] * 100 + uu[i + 1]);
b[j] = (double)((int)vv[i] * 100 + vv[i + 1]);
i += 2;
}
/* zero fill the second half of the arrays */
for (j = nn2; j < nn; j++)
{
a[j] = 0.0;
b[j] = 0.0;
}
/* perform the forward Fourier transforms for both numbers */
M_rdft(nn, 1, a);
M_rdft(nn, 1, b);
/* perform the convolution ... */
b[0] *= a[0];
b[1] *= a[1];
for (j = 3; j <= nn; j += 2)
{
dtemp = b[j - 1];
b[j - 1] = dtemp * a[j - 1] - b[j] * a[j];
b[j] = dtemp * a[j] + b[j] * a[j - 1];
}
/* perform the inverse transform on the result */
M_rdft(nn, -1, b);
/* perform a final pass to release all the carries */
/* we are still in base 10000 at this point */
carry = 0.0;
j = nn;
nnr = 2.0 / (double)nn;
while (1)
{
dtemp = b[--j] * nnr + carry + 0.5;
ul = (unsigned long)(dtemp * 1.0E-4);
carry = (double)ul;
b[j] = dtemp - carry * 10000.0;
if (j == 0)
break;
}
/* copy result to our destination after converting back to base 100 */
w0 = ww;
M_get_div_rem((int)ul, w0, (w0 + 1));
for (j = 0; j <= (nn - 2); j++)
{
w0 += 2;
M_get_div_rem((int)b[j], w0, (w0 + 1));
}
if (mflag)
{
MAPM_FREE(b);
MAPM_FREE(a);
}
}
/****************************************************************************/
/*
* The following info is from Takuya OOURA's documentation :
*
* NOTE : MAPM only uses the 'RDFT' function (as well as the
* functions RDFT calls). All the code from here down
* in this file is from Takuya OOURA. The only change I
* made was to add 'M_' in front of all the functions
* I used. This was to guard against any possible
* name collisions in the future.
*
* MCR 06 July 2000
*
*
* General Purpose FFT (Fast Fourier/Cosine/Sine Transform) Package
*
* Description:
* A package to calculate Discrete Fourier/Cosine/Sine Transforms of
* 1-dimensional sequences of length 2^N.
*
* fft4g_h.c : FFT Package in C - Simple Version I (radix 4,2)
*
* rdft: Real Discrete Fourier Transform
*
* Method:
* -------- rdft --------
* A method with a following butterfly operation appended to "cdft".
* In forward transform :
* A[k] = sum_j=0^n-1 a[j]*W(n)^(j*k), 0<=k<=n/2,
* W(n) = exp(2*pi*i/n),
* this routine makes an array x[] :
* x[j] = a[2*j] + i*a[2*j+1], 0<=j<n/2
* and calls "cdft" of length n/2 :
* X[k] = sum_j=0^n/2-1 x[j] * W(n/2)^(j*k), 0<=k<n.
* The result A[k] are :
* A[k] = X[k] - (1+i*W(n)^k)/2 * (X[k]-conjg(X[n/2-k])),
* A[n/2-k] = X[n/2-k] +
* conjg((1+i*W(n)^k)/2 * (X[k]-conjg(X[n/2-k]))),
* 0<=k<=n/2
* (notes: conjg() is a complex conjugate, X[n/2]=X[0]).
* ----------------------
*
* Reference:
* * Masatake MORI, Makoto NATORI, Tatuo TORII: Suchikeisan,
* Iwanamikouzajyouhoukagaku18, Iwanami, 1982 (Japanese)
* * Henri J. Nussbaumer: Fast Fourier Transform and Convolution
* Algorithms, Springer Verlag, 1982
* * C. S. Burrus, Notes on the FFT (with large FFT paper list)
* http://www-dsp.rice.edu/research/fft/fftnote.asc
*
* Copyright:
* Copyright(C) 1996-1999 Takuya OOURA
* email: ooura@mmm.t.u-tokyo.ac.jp
* download: http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html
* You may use, copy, modify this code for any purpose and
* without fee. You may distribute this ORIGINAL package.
*/
/*
functions
rdft: Real Discrete Fourier Transform
function prototypes
void rdft(int, int, double *);
-------- Real DFT / Inverse of Real DFT --------
[definition]
<case1> RDFT
R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2
I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0<k<n/2
<case2> IRDFT (excluding scale)
a[k] = (R[0] + R[n/2]*cos(pi*k))/2 +
sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) +
sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k<n
[usage]
<case1>
rdft(n, 1, a);
<case2>
rdft(n, -1, a);
[parameters]
n :data length (int)
n >= 2, n = power of 2
a[0...n-1] :input/output data (double *)
<case1>
output data
a[2*k] = R[k], 0<=k<n/2
a[2*k+1] = I[k], 0<k<n/2
a[1] = R[n/2]
<case2>
input data
a[2*j] = R[j], 0<=j<n/2
a[2*j+1] = I[j], 0<j<n/2
a[1] = R[n/2]
[remark]
Inverse of
rdft(n, 1, a);
is
rdft(n, -1, a);
for (j = 0; j <= n - 1; j++) {
a[j] *= 2.0 / n;
}
*/
void M_rdft(int n, int isgn, double *a)
{
double xi;
if (isgn >= 0)
{
if (n > 4)
{
M_bitrv2(n, a);
M_cftfsub(n, a);
M_rftfsub(n, a);
}
else if (n == 4)
{
M_cftfsub(n, a);
}
xi = a[0] - a[1];
a[0] += a[1];
a[1] = xi;
}
else
{
a[1] = 0.5 * (a[0] - a[1]);
a[0] -= a[1];
if (n > 4)
{
M_rftbsub(n, a);
M_bitrv2(n, a);
M_cftbsub(n, a);
}
else if (n == 4)
{
M_cftfsub(n, a);
}
}
}
void M_bitrv2(int n, double *a)
{
int j0, k0, j1, k1, l, m, i, j, k;
double xr, xi, yr, yi;
l = n >> 2;
m = 2;
while (m < l)
{
l >>= 1;
m <<= 1;
}
if (m == l)
{
j0 = 0;
for (k0 = 0; k0 < m; k0 += 2)
{
k = k0;
for (j = j0; j < j0 + k0; j += 2)
{
xr = a[j];
xi = a[j + 1];
yr = a[k];
yi = a[k + 1];
a[j] = yr;
a[j + 1] = yi;
a[k] = xr;
a[k + 1] = xi;
j1 = j + m;
k1 = k + 2 * m;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += m;
k1 -= m;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += m;
k1 += 2 * m;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
for (i = n >> 1; i > (k ^= i); i >>= 1);
}
j1 = j0 + k0 + m;
k1 = j1 + m;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
for (i = n >> 1; i > (j0 ^= i); i >>= 1);
}
}
else
{
j0 = 0;
for (k0 = 2; k0 < m; k0 += 2)
{
for (i = n >> 1; i > (j0 ^= i); i >>= 1);
k = k0;
for (j = j0; j < j0 + k0; j += 2)
{
xr = a[j];
xi = a[j + 1];
yr = a[k];
yi = a[k + 1];
a[j] = yr;
a[j + 1] = yi;
a[k] = xr;
a[k + 1] = xi;
j1 = j + m;
k1 = k + m;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
for (i = n >> 1; i > (k ^= i); i >>= 1);
}
}
}
}
void M_cftfsub(int n, double *a)
{
int j, j1, j2, j3, l;
double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
l = 2;
if (n > 8)
{
M_cft1st(n, a);
l = 8;
while ((l << 2) < n)
{
M_cftmdl(n, l, a);
l <<= 2;
}
}
if ((l << 2) == n)
{
for (j = 0; j < l; j += 2)
{
j1 = j + l;
j2 = j1 + l;
j3 = j2 + l;
x0r = a[j] + a[j1];
x0i = a[j + 1] + a[j1 + 1];
x1r = a[j] - a[j1];
x1i = a[j + 1] - a[j1 + 1];
x2r = a[j2] + a[j3];
x2i = a[j2 + 1] + a[j3 + 1];
x3r = a[j2] - a[j3];
x3i = a[j2 + 1] - a[j3 + 1];
a[j] = x0r + x2r;
a[j + 1] = x0i + x2i;
a[j2] = x0r - x2r;
a[j2 + 1] = x0i - x2i;
a[j1] = x1r - x3i;
a[j1 + 1] = x1i + x3r;
a[j3] = x1r + x3i;
a[j3 + 1] = x1i - x3r;
}
}
else
{
for (j = 0; j < l; j += 2)
{
j1 = j + l;
x0r = a[j] - a[j1];
x0i = a[j + 1] - a[j1 + 1];
a[j] += a[j1];
a[j + 1] += a[j1 + 1];
a[j1] = x0r;
a[j1 + 1] = x0i;
}
}
}
void M_cftbsub(int n, double *a)
{
int j, j1, j2, j3, l;
double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
l = 2;
if (n > 8)
{
M_cft1st(n, a);
l = 8;
while ((l << 2) < n)
{
M_cftmdl(n, l, a);
l <<= 2;
}
}
if ((l << 2) == n)
{
for (j = 0; j < l; j += 2)
{
j1 = j + l;
j2 = j1 + l;
j3 = j2 + l;
x0r = a[j] + a[j1];
x0i = -a[j + 1] - a[j1 + 1];
x1r = a[j] - a[j1];
x1i = -a[j + 1] + a[j1 + 1];
x2r = a[j2] + a[j3];
x2i = a[j2 + 1] + a[j3 + 1];
x3r = a[j2] - a[j3];
x3i = a[j2 + 1] - a[j3 + 1];
a[j] = x0r + x2r;
a[j + 1] = x0i - x2i;
a[j2] = x0r - x2r;
a[j2 + 1] = x0i + x2i;
a[j1] = x1r - x3i;
a[j1 + 1] = x1i - x3r;
a[j3] = x1r + x3i;
a[j3 + 1] = x1i + x3r;
}
}
else
{
for (j = 0; j < l; j += 2)
{
j1 = j + l;
x0r = a[j] - a[j1];
x0i = -a[j + 1] + a[j1 + 1];
a[j] += a[j1];
a[j + 1] = -a[j + 1] - a[j1 + 1];
a[j1] = x0r;
a[j1 + 1] = x0i;
}
}
}
void M_cft1st(int n, double *a)
{
int j, kj, kr;
double ew, wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i;
double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
x0r = a[0] + a[2];
x0i = a[1] + a[3];
x1r = a[0] - a[2];
x1i = a[1] - a[3];
x2r = a[4] + a[6];
x2i = a[5] + a[7];
x3r = a[4] - a[6];
x3i = a[5] - a[7];
a[0] = x0r + x2r;
a[1] = x0i + x2i;
a[4] = x0r - x2r;
a[5] = x0i - x2i;
a[2] = x1r - x3i;
a[3] = x1i + x3r;
a[6] = x1r + x3i;
a[7] = x1i - x3r;
wn4r = WR5000;
x0r = a[8] + a[10];
x0i = a[9] + a[11];
x1r = a[8] - a[10];
x1i = a[9] - a[11];
x2r = a[12] + a[14];
x2i = a[13] + a[15];
x3r = a[12] - a[14];
x3i = a[13] - a[15];
a[8] = x0r + x2r;
a[9] = x0i + x2i;
a[12] = x2i - x0i;
a[13] = x0r - x2r;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[10] = wn4r * (x0r - x0i);
a[11] = wn4r * (x0r + x0i);
x0r = x3i + x1r;
x0i = x3r - x1i;
a[14] = wn4r * (x0i - x0r);
a[15] = wn4r * (x0i + x0r);
ew = MM_PI_2 / n;
kr = 0;
for (j = 16; j < n; j += 16)
{
for (kj = n >> 2; kj > (kr ^= kj); kj >>= 1);
wk1r = cos(ew * kr);
wk1i = sin(ew * kr);
wk2r = 1 - 2 * wk1i * wk1i;
wk2i = 2 * wk1i * wk1r;
wk3r = wk1r - 2 * wk2i * wk1i;
wk3i = 2 * wk2i * wk1r - wk1i;
x0r = a[j] + a[j + 2];
x0i = a[j + 1] + a[j + 3];
x1r = a[j] - a[j + 2];
x1i = a[j + 1] - a[j + 3];
x2r = a[j + 4] + a[j + 6];
x2i = a[j + 5] + a[j + 7];
x3r = a[j + 4] - a[j + 6];
x3i = a[j + 5] - a[j + 7];
a[j] = x0r + x2r;
a[j + 1] = x0i + x2i;
x0r -= x2r;
x0i -= x2i;
a[j + 4] = wk2r * x0r - wk2i * x0i;
a[j + 5] = wk2r * x0i + wk2i * x0r;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[j + 2] = wk1r * x0r - wk1i * x0i;
a[j + 3] = wk1r * x0i + wk1i * x0r;
x0r = x1r + x3i;
x0i = x1i - x3r;
a[j + 6] = wk3r * x0r - wk3i * x0i;
a[j + 7] = wk3r * x0i + wk3i * x0r;
x0r = wn4r * (wk1r - wk1i);
wk1i = wn4r * (wk1r + wk1i);
wk1r = x0r;
wk3r = wk1r - 2 * wk2r * wk1i;
wk3i = 2 * wk2r * wk1r - wk1i;
x0r = a[j + 8] + a[j + 10];
x0i = a[j + 9] + a[j + 11];
x1r = a[j + 8] - a[j + 10];
x1i = a[j + 9] - a[j + 11];
x2r = a[j + 12] + a[j + 14];
x2i = a[j + 13] + a[j + 15];
x3r = a[j + 12] - a[j + 14];
x3i = a[j + 13] - a[j + 15];
a[j + 8] = x0r + x2r;
a[j + 9] = x0i + x2i;
x0r -= x2r;
x0i -= x2i;
a[j + 12] = -wk2i * x0r - wk2r * x0i;
a[j + 13] = -wk2i * x0i + wk2r * x0r;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[j + 10] = wk1r * x0r - wk1i * x0i;
a[j + 11] = wk1r * x0i + wk1i * x0r;
x0r = x1r + x3i;
x0i = x1i - x3r;
a[j + 14] = wk3r * x0r - wk3i * x0i;
a[j + 15] = wk3r * x0i + wk3i * x0r;
}
}
void M_cftmdl(int n, int l, double *a)
{
int j, j1, j2, j3, k, kj, kr, m, m2;
double ew, wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i;
double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
m = l << 2;
for (j = 0; j < l; j += 2)
{
j1 = j + l;
j2 = j1 + l;
j3 = j2 + l;
x0r = a[j] + a[j1];
x0i = a[j + 1] + a[j1 + 1];
x1r = a[j] - a[j1];
x1i = a[j + 1] - a[j1 + 1];
x2r = a[j2] + a[j3];
x2i = a[j2 + 1] + a[j3 + 1];
x3r = a[j2] - a[j3];
x3i = a[j2 + 1] - a[j3 + 1];
a[j] = x0r + x2r;
a[j + 1] = x0i + x2i;
a[j2] = x0r - x2r;
a[j2 + 1] = x0i - x2i;
a[j1] = x1r - x3i;
a[j1 + 1] = x1i + x3r;
a[j3] = x1r + x3i;
a[j3 + 1] = x1i - x3r;
}
wn4r = WR5000;
for (j = m; j < l + m; j += 2)
{
j1 = j + l;
j2 = j1 + l;
j3 = j2 + l;
x0r = a[j] + a[j1];
x0i = a[j + 1] + a[j1 + 1];
x1r = a[j] - a[j1];
x1i = a[j + 1] - a[j1 + 1];
x2r = a[j2] + a[j3];
x2i = a[j2 + 1] + a[j3 + 1];
x3r = a[j2] - a[j3];
x3i = a[j2 + 1] - a[j3 + 1];
a[j] = x0r + x2r;
a[j + 1] = x0i + x2i;
a[j2] = x2i - x0i;
a[j2 + 1] = x0r - x2r;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[j1] = wn4r * (x0r - x0i);
a[j1 + 1] = wn4r * (x0r + x0i);
x0r = x3i + x1r;
x0i = x3r - x1i;
a[j3] = wn4r * (x0i - x0r);
a[j3 + 1] = wn4r * (x0i + x0r);
}
ew = MM_PI_2 / n;
kr = 0;
m2 = 2 * m;
for (k = m2; k < n; k += m2)
{
for (kj = n >> 2; kj > (kr ^= kj); kj >>= 1);
wk1r = cos(ew * kr);
wk1i = sin(ew * kr);
wk2r = 1 - 2 * wk1i * wk1i;
wk2i = 2 * wk1i * wk1r;
wk3r = wk1r - 2 * wk2i * wk1i;
wk3i = 2 * wk2i * wk1r - wk1i;
for (j = k; j < l + k; j += 2)
{
j1 = j + l;
j2 = j1 + l;
j3 = j2 + l;
x0r = a[j] + a[j1];
x0i = a[j + 1] + a[j1 + 1];
x1r = a[j] - a[j1];
x1i = a[j + 1] - a[j1 + 1];
x2r = a[j2] + a[j3];
x2i = a[j2 + 1] + a[j3 + 1];
x3r = a[j2] - a[j3];
x3i = a[j2 + 1] - a[j3 + 1];
a[j] = x0r + x2r;
a[j + 1] = x0i + x2i;
x0r -= x2r;
x0i -= x2i;
a[j2] = wk2r * x0r - wk2i * x0i;
a[j2 + 1] = wk2r * x0i + wk2i * x0r;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[j1] = wk1r * x0r - wk1i * x0i;
a[j1 + 1] = wk1r * x0i + wk1i * x0r;
x0r = x1r + x3i;
x0i = x1i - x3r;
a[j3] = wk3r * x0r - wk3i * x0i;
a[j3 + 1] = wk3r * x0i + wk3i * x0r;
}
x0r = wn4r * (wk1r - wk1i);
wk1i = wn4r * (wk1r + wk1i);
wk1r = x0r;
wk3r = wk1r - 2 * wk2r * wk1i;
wk3i = 2 * wk2r * wk1r - wk1i;
for (j = k + m; j < l + (k + m); j += 2)
{
j1 = j + l;
j2 = j1 + l;
j3 = j2 + l;
x0r = a[j] + a[j1];
x0i = a[j + 1] + a[j1 + 1];
x1r = a[j] - a[j1];
x1i = a[j + 1] - a[j1 + 1];
x2r = a[j2] + a[j3];
x2i = a[j2 + 1] + a[j3 + 1];
x3r = a[j2] - a[j3];
x3i = a[j2 + 1] - a[j3 + 1];
a[j] = x0r + x2r;
a[j + 1] = x0i + x2i;
x0r -= x2r;
x0i -= x2i;
a[j2] = -wk2i * x0r - wk2r * x0i;
a[j2 + 1] = -wk2i * x0i + wk2r * x0r;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[j1] = wk1r * x0r - wk1i * x0i;
a[j1 + 1] = wk1r * x0i + wk1i * x0r;
x0r = x1r + x3i;
x0i = x1i - x3r;
a[j3] = wk3r * x0r - wk3i * x0i;
a[j3 + 1] = wk3r * x0i + wk3i * x0r;
}
}
}
void M_rftfsub(int n, double *a)
{
int i, i0, j, k;
double ec, w1r, w1i, wkr, wki, wdr, wdi, ss, xr, xi, yr, yi;
ec = 2 * MM_PI_2 / n;
wkr = 0;
wki = 0;
wdi = cos(ec);
wdr = sin(ec);
wdi *= wdr;
wdr *= wdr;
w1r = 1 - 2 * wdr;
w1i = 2 * wdi;
ss = 2 * w1i;
i = n >> 1;
while (1)
{
i0 = i - 4 * RDFT_LOOP_DIV;
if (i0 < 4)
{
i0 = 4;
}
for (j = i - 4; j >= i0; j -= 4)
{
k = n - j;
xr = a[j + 2] - a[k - 2];
xi = a[j + 3] + a[k - 1];
yr = wdr * xr - wdi * xi;
yi = wdr * xi + wdi * xr;
a[j + 2] -= yr;
a[j + 3] -= yi;
a[k - 2] += yr;
a[k - 1] -= yi;
wkr += ss * wdi;
wki += ss * (0.5 - wdr);
xr = a[j] - a[k];
xi = a[j + 1] + a[k + 1];
yr = wkr * xr - wki * xi;
yi = wkr * xi + wki * xr;
a[j] -= yr;
a[j + 1] -= yi;
a[k] += yr;
a[k + 1] -= yi;
wdr += ss * wki;
wdi += ss * (0.5 - wkr);
}
if (i0 == 4)
{
break;
}
wkr = 0.5 * sin(ec * i0);
wki = 0.5 * cos(ec * i0);
wdr = 0.5 - (wkr * w1r - wki * w1i);
wdi = wkr * w1i + wki * w1r;
wkr = 0.5 - wkr;
i = i0;
}
xr = a[2] - a[n - 2];
xi = a[3] + a[n - 1];
yr = wdr * xr - wdi * xi;
yi = wdr * xi + wdi * xr;
a[2] -= yr;
a[3] -= yi;
a[n - 2] += yr;
a[n - 1] -= yi;
}
void M_rftbsub(int n, double *a)
{
int i, i0, j, k;
double ec, w1r, w1i, wkr, wki, wdr, wdi, ss, xr, xi, yr, yi;
ec = 2 * MM_PI_2 / n;
wkr = 0;
wki = 0;
wdi = cos(ec);
wdr = sin(ec);
wdi *= wdr;
wdr *= wdr;
w1r = 1 - 2 * wdr;
w1i = 2 * wdi;
ss = 2 * w1i;
i = n >> 1;
a[i + 1] = -a[i + 1];
while (1)
{
i0 = i - 4 * RDFT_LOOP_DIV;
if (i0 < 4)
{
i0 = 4;
}
for (j = i - 4; j >= i0; j -= 4)
{
k = n - j;
xr = a[j + 2] - a[k - 2];
xi = a[j + 3] + a[k - 1];
yr = wdr * xr + wdi * xi;
yi = wdr * xi - wdi * xr;
a[j + 2] -= yr;
a[j + 3] = yi - a[j + 3];
a[k - 2] += yr;
a[k - 1] = yi - a[k - 1];
wkr += ss * wdi;
wki += ss * (0.5 - wdr);
xr = a[j] - a[k];
xi = a[j + 1] + a[k + 1];
yr = wkr * xr + wki * xi;
yi = wkr * xi - wki * xr;
a[j] -= yr;
a[j + 1] = yi - a[j + 1];
a[k] += yr;
a[k + 1] = yi - a[k + 1];
wdr += ss * wki;
wdi += ss * (0.5 - wkr);
}
if (i0 == 4)
{
break;
}
wkr = 0.5 * sin(ec * i0);
wki = 0.5 * cos(ec * i0);
wdr = 0.5 - (wkr * w1r - wki * w1i);
wdi = wkr * w1i + wki * w1r;
wkr = 0.5 - wkr;
i = i0;
}
xr = a[2] - a[n - 2];
xi = a[3] + a[n - 1];
yr = wdr * xr + wdi * xi;
yi = wdr * xi - wdi * xr;
a[2] -= yr;
a[3] = yi - a[3];
a[n - 2] += yr;
a[n - 1] = yi - a[n - 1];
a[1] = -a[1];
}

View file

@ -0,0 +1,120 @@
/*
* M_APM - mapm_flr.c
*
* Copyright (C) 2001 - 2007 Michael C. Ring
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted. Permission to distribute
* the modified code is granted. Modifications are to be distributed by
* using the file 'license.txt' as a template to modify the file header.
* 'license.txt' is available in the official MAPM distribution.
*
* This software is provided "as is" without express or implied warranty.
*/
/*
*
* This file contains the floor and ceil functions
*
*/
#include "pgAdmin3.h"
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
/*
* input floor ceil
* ----- ------ ------
* 329.0 329.0 329.0
* -837.0 -837.0 -837.0
* 372.64 372.0 373.0
* -237.52 -238.0 -237.0
*/
/****************************************************************************/
/*
* return the nearest integer <= input
*/
void m_apm_floor(M_APM bb, M_APM aa)
{
M_APM mtmp;
m_apm_copy(bb, aa);
if (m_apm_is_integer(bb)) /* if integer, we're done */
return;
if (bb->m_apm_exponent <= 0) /* if |bb| < 1, result is -1 or 0 */
{
if (bb->m_apm_sign < 0)
m_apm_negate(bb, MM_One);
else
M_set_to_zero(bb);
return;
}
if (bb->m_apm_sign < 0)
{
mtmp = M_get_stack_var();
m_apm_negate(mtmp, bb);
mtmp->m_apm_datalength = mtmp->m_apm_exponent;
M_apm_normalize(mtmp);
m_apm_add(bb, mtmp, MM_One);
bb->m_apm_sign = -1;
M_restore_stack(1);
}
else
{
bb->m_apm_datalength = bb->m_apm_exponent;
M_apm_normalize(bb);
}
}
/****************************************************************************/
/*
* return the nearest integer >= input
*/
void m_apm_ceil(M_APM bb, M_APM aa)
{
M_APM mtmp;
m_apm_copy(bb, aa);
if (m_apm_is_integer(bb)) /* if integer, we're done */
return;
if (bb->m_apm_exponent <= 0) /* if |bb| < 1, result is 0 or 1 */
{
if (bb->m_apm_sign < 0)
M_set_to_zero(bb);
else
m_apm_copy(bb, MM_One);
return;
}
if (bb->m_apm_sign < 0)
{
bb->m_apm_datalength = bb->m_apm_exponent;
M_apm_normalize(bb);
}
else
{
mtmp = M_get_stack_var();
m_apm_copy(mtmp, bb);
mtmp->m_apm_datalength = mtmp->m_apm_exponent;
M_apm_normalize(mtmp);
m_apm_add(bb, mtmp, MM_One);
M_restore_stack(1);
}
}
/****************************************************************************/

View file

@ -0,0 +1,415 @@
/*
* M_APM - mapm_fpf.c
*
* Copyright (C) 2001 - 2007 Michael C. Ring
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted. Permission to distribute
* the modified code is granted. Modifications are to be distributed by
* using the file 'license.txt' as a template to modify the file header.
* 'license.txt' is available in the official MAPM distribution.
*
* This software is provided "as is" without express or implied warranty.
*/
/*
*
* This file contains the Fixed Point Formatting functions
*
*/
#include "pgAdmin3.h"
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
#include <ctype.h>
/****************************************************************************/
char *m_apm_to_fixpt_stringexp(int dplaces, M_APM atmp,
char ch_radx, char ch_sep, int ct_sep)
{
int places, xp, dl, ii;
char *cpr;
places = dplaces;
dl = atmp->m_apm_datalength;
xp = atmp->m_apm_exponent;
if (places < 0) /* show ALL digits */
{
if (xp < 0)
ii = dl - xp;
else
{
if (dl > xp)
ii = dl;
else
ii = xp;
}
}
else
{
ii = places;
if (xp > 0)
ii += xp;
}
if (ct_sep != 0 && ch_sep != 0 && xp > 0)
ii += xp / ct_sep;
if ((cpr = (char *)MAPM_MALLOC((ii + 32) * sizeof(char))) == NULL)
return(NULL);
m_apm_to_fixpt_stringex(cpr, places, atmp, ch_radx, ch_sep, ct_sep);
return(cpr);
}
/****************************************************************************/
void m_apm_to_fixpt_stringex(char *s, int dplaces, M_APM atmp,
char ch_radix, char ch_sep, int count_sep)
{
M_APM btmp;
char ch, *cpd, *cps;
int ii, jj, kk, ct, dl, xp, no_sep_flg, places;
btmp = M_get_stack_var();
places = dplaces;
cpd = s;
no_sep_flg = FALSE;
m_apm_absolute_value(btmp, atmp); /* do conversion of positive number */
if (ch_sep == 0 || count_sep == 0) /* no separator char OR count */
no_sep_flg = TRUE;
/* determine how much memory to get for the temp string */
dl = btmp->m_apm_datalength;
xp = btmp->m_apm_exponent;
if (places < 0) /* show ALL digits */
{
if (xp < 0)
ii = dl - xp;
else
{
if (dl > xp)
ii = dl;
else
ii = xp;
}
}
else
{
ii = places;
if (xp > 0)
ii += xp;
}
if ((cps = (char *)MAPM_MALLOC((ii + 32) * sizeof(char))) == NULL)
{
/* fatal, this does not return */
M_apm_log_error_msg(M_APM_FATAL,
"\'m_apm_to_fixpt_stringex\', Out of memory");
}
m_apm_to_fixpt_string(cps, places, btmp);
/*
* the converted string may be all 'zero', 0.0000...
* if so and the original number is negative,
* do NOT set the '-' sign of our output string.
*/
if (atmp->m_apm_sign == -1) /* if input number negative */
{
kk = 0;
jj = 0;
while (TRUE)
{
ch = cps[kk++];
if ((ch == '\0') || (jj != 0))
break;
if (isdigit((int)ch))
{
if (ch != '0')
jj = 1;
}
}
if (jj)
*cpd++ = '-';
}
ct = M_strposition(cps, (char *) "."); /* find the default (.) radix char */
if (ct == -1) /* if not found .. */
{
strcat(cps, "."); /* add one */
ct = M_strposition(cps, (char *) "."); /* and then find it */
}
if (places == 0) /* int format, terminate at radix char */
cps[ct] = '\0';
else
cps[ct] = ch_radix; /* assign the radix char */
/*
* if the number is small enough to not have any separator char's ...
*/
if (ct <= count_sep)
no_sep_flg = TRUE;
if (no_sep_flg)
{
strcpy(cpd, cps);
}
else
{
jj = 0;
kk = count_sep;
ii = ct / count_sep;
if ((ii = ct - ii * count_sep) == 0)
ii = count_sep;
while (TRUE) /* write out the first 1,2 */
{
/* (up to count_sep) digits */
*cpd++ = cps[jj++];
if (--ii == 0)
break;
}
while (TRUE) /* write rest of the string */
{
if (kk == count_sep) /* write a new separator char */
{
if (jj != ct) /* unless we're at the radix */
{
*cpd++ = ch_sep; /* note that this also disables */
kk = 0; /* the separator char AFTER */
} /* the radix char */
}
if ((*cpd++ = cps[jj++]) == '\0')
break;
kk++;
}
}
MAPM_FREE(cps);
M_restore_stack(1);
}
/****************************************************************************/
void m_apm_to_fixpt_string(char *ss, int dplaces, M_APM mtmp)
{
M_APM ctmp;
void *vp;
int places, i2, ii, jj, kk, xp, dl, numb;
UCHAR *ucp, numdiv, numrem;
char *cpw, *cpd, sbuf[128];
ctmp = M_get_stack_var();
vp = NULL;
cpd = ss;
places = dplaces;
/* just want integer portion if places == 0 */
if (places == 0)
{
if (mtmp->m_apm_sign >= 0)
m_apm_add(ctmp, mtmp, MM_0_5);
else
m_apm_subtract(ctmp, mtmp, MM_0_5);
m_apm_to_integer_string(cpd, ctmp);
M_restore_stack(1);
return;
}
if (places > 0)
M_apm_round_fixpt(ctmp, places, mtmp);
else
m_apm_copy(ctmp, mtmp); /* show ALL digits */
if (ctmp->m_apm_sign == 0) /* result is 0 */
{
if (places < 0)
{
cpd[0] = '0'; /* "0.0" */
cpd[1] = '.';
cpd[2] = '0';
cpd[3] = '\0';
}
else
{
memset(cpd, '0', (places + 2)); /* pre-load string with all '0' */
cpd[1] = '.';
cpd[places + 2] = '\0';
}
M_restore_stack(1);
return;
}
xp = ctmp->m_apm_exponent;
dl = ctmp->m_apm_datalength;
numb = (dl + 1) >> 1;
if (places < 0)
{
if (dl > xp)
jj = dl + 16;
else
jj = xp + 16;
}
else
{
jj = places + 16;
if (xp > 0)
jj += xp;
}
if (jj > 112)
{
if ((vp = (void *)MAPM_MALLOC((jj + 16) * sizeof(char))) == NULL)
{
/* fatal, this does not return */
M_apm_log_error_msg(M_APM_FATAL,
"\'m_apm_to_fixpt_string\', Out of memory");
}
cpw = (char *)vp;
}
else
{
cpw = sbuf;
}
/*
* at this point, the number is non-zero and the output
* string will contain at least 1 significant digit.
*/
if (ctmp->m_apm_sign == -1) /* negative number */
{
*cpd++ = '-';
}
ucp = ctmp->m_apm_data;
ii = 0;
/* convert MAPM num to ASCII digits and store in working char array */
while (TRUE)
{
M_get_div_rem_10((int)(*ucp++), &numdiv, &numrem);
cpw[ii++] = numdiv + '0';
cpw[ii++] = numrem + '0';
if (--numb == 0)
break;
}
i2 = ii; /* save for later */
if (places < 0) /* show ALL digits */
{
places = dl - xp;
if (places < 1)
places = 1;
}
/* pad with trailing zeros if needed */
kk = xp + places + 2 - ii;
if (kk > 0)
memset(&cpw[ii], '0', kk);
if (xp > 0) /* |num| >= 1, NO lead-in "0.nnn" */
{
ii = xp + places + 1;
jj = 0;
for (kk = 0; kk < ii; kk++)
{
if (kk == xp)
cpd[jj++] = '.';
cpd[jj++] = cpw[kk];
}
cpd[ii] = '\0';
}
else /* |num| < 1, have lead-in "0.nnn" */
{
jj = 2 - xp;
ii = 2 + places;
memset(cpd, '0', (ii + 1)); /* pre-load string with all '0' */
cpd[1] = '.'; /* assign decimal point */
for (kk = 0; kk < i2; kk++)
{
cpd[jj++] = cpw[kk];
}
cpd[ii] = '\0';
}
if (vp != NULL)
MAPM_FREE(vp);
M_restore_stack(1);
}
/****************************************************************************/
void M_apm_round_fixpt(M_APM btmp, int places, M_APM atmp)
{
int xp, ii;
xp = atmp->m_apm_exponent;
ii = xp + places - 1;
M_set_to_zero(btmp); /* assume number is too small so the net result is 0 */
if (ii >= 0)
{
m_apm_round(btmp, ii, atmp);
}
else
{
if (ii == -1) /* next digit is significant which may round up */
{
if (atmp->m_apm_data[0] >= 50) /* digit >= 5, round up */
{
m_apm_copy(btmp, atmp);
btmp->m_apm_data[0] = 10;
btmp->m_apm_exponent += 1;
btmp->m_apm_datalength = 1;
M_apm_normalize(btmp);
}
}
}
}
/****************************************************************************/

View file

@ -0,0 +1,260 @@
/*
* M_APM - mapm_gcd.c
*
* Copyright (C) 2001 - 2007 Michael C. Ring
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted. Permission to distribute
* the modified code is granted. Modifications are to be distributed by
* using the file 'license.txt' as a template to modify the file header.
* 'license.txt' is available in the official MAPM distribution.
*
* This software is provided "as is" without express or implied warranty.
*/
/*
*
* This file contains the GCD and LCM functions
*
*/
#include "pgAdmin3.h"
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
/****************************************************************************/
/*
* From Knuth, The Art of Computer Programming:
*
* This is the binary GCD algorithm as described
* in the book (Algorithm B)
*/
void m_apm_gcd(M_APM r, M_APM u, M_APM v)
{
M_APM tmpM, tmpN, tmpT, tmpU, tmpV;
int kk, kr, mm;
long pow_2;
/* 'is_integer' will return 0 || 1 */
if ((m_apm_is_integer(u) + m_apm_is_integer(v)) != 2)
{
M_apm_log_error_msg(M_APM_RETURN, "\'m_apm_gcd\', Non-integer input");
M_set_to_zero(r);
return;
}
if (u->m_apm_sign == 0)
{
m_apm_absolute_value(r, v);
return;
}
if (v->m_apm_sign == 0)
{
m_apm_absolute_value(r, u);
return;
}
tmpM = M_get_stack_var();
tmpN = M_get_stack_var();
tmpT = M_get_stack_var();
tmpU = M_get_stack_var();
tmpV = M_get_stack_var();
m_apm_absolute_value(tmpU, u);
m_apm_absolute_value(tmpV, v);
/* Step B1 */
kk = 0;
while (TRUE)
{
mm = 1;
if (m_apm_is_odd(tmpU))
break;
mm = 0;
if (m_apm_is_odd(tmpV))
break;
m_apm_multiply(tmpN, MM_0_5, tmpU);
m_apm_copy(tmpU, tmpN);
m_apm_multiply(tmpN, MM_0_5, tmpV);
m_apm_copy(tmpV, tmpN);
kk++;
}
/* Step B2 */
if (mm)
{
m_apm_negate(tmpT, tmpV);
goto B4;
}
m_apm_copy(tmpT, tmpU);
/* Step: */
B3:
m_apm_multiply(tmpN, MM_0_5, tmpT);
m_apm_copy(tmpT, tmpN);
/* Step: */
B4:
if (m_apm_is_even(tmpT))
goto B3;
/* Step B5 */
if (tmpT->m_apm_sign == 1)
m_apm_copy(tmpU, tmpT);
else
m_apm_negate(tmpV, tmpT);
/* Step B6 */
m_apm_subtract(tmpT, tmpU, tmpV);
if (tmpT->m_apm_sign != 0)
goto B3;
/*
* result = U * 2 ^ kk
*/
if (kk == 0)
m_apm_copy(r, tmpU);
else
{
if (kk == 1)
m_apm_multiply(r, tmpU, MM_Two);
if (kk == 2)
m_apm_multiply(r, tmpU, MM_Four);
if (kk >= 3)
{
mm = kk / 28;
kr = kk % 28;
pow_2 = 1L << kr;
if (mm == 0)
{
m_apm_set_long(tmpN, pow_2);
m_apm_multiply(r, tmpU, tmpN);
}
else
{
m_apm_copy(tmpN, MM_One);
m_apm_set_long(tmpM, 0x10000000L); /* 2 ^ 28 */
while (TRUE)
{
m_apm_multiply(tmpT, tmpN, tmpM);
m_apm_copy(tmpN, tmpT);
if (--mm == 0)
break;
}
if (kr == 0)
{
m_apm_multiply(r, tmpU, tmpN);
}
else
{
m_apm_set_long(tmpM, pow_2);
m_apm_multiply(tmpT, tmpN, tmpM);
m_apm_multiply(r, tmpU, tmpT);
}
}
}
}
M_restore_stack(5);
}
/****************************************************************************/
/*
* u * v
* LCM(u,v) = ------------
* GCD(u,v)
*/
void m_apm_lcm(M_APM r, M_APM u, M_APM v)
{
M_APM tmpN, tmpG;
tmpN = M_get_stack_var();
tmpG = M_get_stack_var();
m_apm_multiply(tmpN, u, v);
m_apm_gcd(tmpG, u, v);
m_apm_integer_divide(r, tmpN, tmpG);
M_restore_stack(2);
}
/****************************************************************************/
#ifdef BIG_COMMENT_BLOCK
/*
* traditional GCD included for reference
* (also useful for testing ...)
*/
/*
* From Knuth, The Art of Computer Programming:
*
* To compute GCD(u,v)
*
* A1:
* if (v == 0) return (u)
* A2:
* t = u mod v
* u = v
* v = t
* goto A1
*/
void m_apm_gcd_traditional(M_APM r, M_APM u, M_APM v)
{
M_APM tmpD, tmpN, tmpU, tmpV;
tmpD = M_get_stack_var();
tmpN = M_get_stack_var();
tmpU = M_get_stack_var();
tmpV = M_get_stack_var();
m_apm_absolute_value(tmpU, u);
m_apm_absolute_value(tmpV, v);
while (TRUE)
{
if (tmpV->m_apm_sign == 0)
break;
m_apm_integer_div_rem(tmpD, tmpN, tmpU, tmpV);
m_apm_copy(tmpU, tmpV);
m_apm_copy(tmpV, tmpN);
}
m_apm_copy(r, tmpU);
M_restore_stack(4);
}
/****************************************************************************/
#endif

View file

@ -0,0 +1,152 @@
/*
* M_APM - mapm_lg2.c
*
* Copyright (C) 2003 - 2007 Michael C. Ring
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted. Permission to distribute
* the modified code is granted. Modifications are to be distributed by
* using the file 'license.txt' as a template to modify the file header.
* 'license.txt' is available in the official MAPM distribution.
*
* This software is provided "as is" without express or implied warranty.
*/
/*
*
* This file contains the iterative function to compute the LOG
* This is an internal function to the library and is not intended
* to be called directly by the user.
*
*/
#include "pgAdmin3.h"
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
/****************************************************************************/
/*
* compute rr = log(nn)
*
* input is assumed to not exceed the exponent range of a normal
* 'C' double ( |exponent| must be < 308)
*/
/****************************************************************************/
void M_log_solve_cubic(M_APM rr, int places, M_APM nn)
{
M_APM tmp0, tmp1, tmp2, tmp3, guess;
int ii, maxp, tolerance, local_precision;
guess = M_get_stack_var();
tmp0 = M_get_stack_var();
tmp1 = M_get_stack_var();
tmp2 = M_get_stack_var();
tmp3 = M_get_stack_var();
M_get_log_guess(guess, nn);
tolerance = -(places + 4);
maxp = places + 16;
local_precision = 18;
/* Use the following iteration to solve for log :
exp(X) - N
X = X - 2 * ------------
n+1 exp(X) + N
this is a cubically convergent algorithm
(each iteration yields 3X more digits)
*/
ii = 0;
while (TRUE)
{
m_apm_exp(tmp1, local_precision, guess);
m_apm_subtract(tmp3, tmp1, nn);
m_apm_add(tmp2, tmp1, nn);
m_apm_divide(tmp1, local_precision, tmp3, tmp2);
m_apm_multiply(tmp0, MM_Two, tmp1);
m_apm_subtract(tmp3, guess, tmp0);
if (ii != 0)
{
if (((3 * tmp0->m_apm_exponent) < tolerance) || (tmp0->m_apm_sign == 0))
break;
}
m_apm_round(guess, local_precision, tmp3);
local_precision *= 3;
if (local_precision > maxp)
local_precision = maxp;
ii = 1;
}
m_apm_round(rr, places, tmp3);
M_restore_stack(5);
}
/****************************************************************************/
/*
* find log(N)
*
* if places < 360
* solve with cubically convergent algorithm above
*
* else
*
* let 'X' be 'close' to the solution (we use ~110 decimal places)
*
* let Y = N * exp(-X) - 1
*
* then
*
* log(N) = X + log(1 + Y)
*
* since 'Y' will be small, we can use the efficient log_near_1 algorithm.
*
*/
void M_log_basic_iteration(M_APM rr, int places, M_APM nn)
{
M_APM tmp0, tmp1, tmp2, tmpX;
if (places < 360)
{
M_log_solve_cubic(rr, places, nn);
}
else
{
tmp0 = M_get_stack_var();
tmp1 = M_get_stack_var();
tmp2 = M_get_stack_var();
tmpX = M_get_stack_var();
M_log_solve_cubic(tmpX, 110, nn);
m_apm_negate(tmp0, tmpX);
m_apm_exp(tmp1, (places + 8), tmp0);
m_apm_multiply(tmp2, tmp1, nn);
m_apm_subtract(tmp1, tmp2, MM_One);
M_log_near_1(tmp0, (places - 104), tmp1);
m_apm_add(tmp1, tmpX, tmp0);
m_apm_round(rr, places, tmp1);
M_restore_stack(4);
}
}
/****************************************************************************/

View file

@ -0,0 +1,204 @@
/*
* M_APM - mapm_lg3.c
*
* Copyright (C) 2003 - 2007 Michael C. Ring
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted. Permission to distribute
* the modified code is granted. Modifications are to be distributed by
* using the file 'license.txt' as a template to modify the file header.
* 'license.txt' is available in the official MAPM distribution.
*
* This software is provided "as is" without express or implied warranty.
*/
/*
*
* This file contains the function to compute log(2), log(10),
* and 1/log(10) to the desired precision using an AGM algorithm.
*
*/
#include "pgAdmin3.h"
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
/*
* using the 'R' function (defined below) for 'N' decimal places :
*
*
* -N -N
* log(2) = R(1, 0.5 * 10 ) - R(1, 10 )
*
*
* -N -N
* log(10) = R(1, 0.1 * 10 ) - R(1, 10 )
*
*
* In general:
*
* -N -N
* log(x) = R(1, 10 / x) - R(1, 10 )
*
*
* I found this on a web site which went into considerable detail
* on the history of log(2). This formula is algebraically identical
* to the formula specified in J. Borwein and P. Borwein's book
* "PI and the AGM". (reference algorithm 7.2)
*/
/****************************************************************************/
/*
* check if our local copy of log(2) & log(10) is precise
* enough for our purpose. if not, calculate them so it's
* as precise as desired, accurate to at least 'places'.
*/
void M_check_log_places(int places)
{
M_APM tmp6, tmp7, tmp8, tmp9;
int dplaces;
dplaces = places + 4;
if (dplaces > MM_lc_log_digits)
{
MM_lc_log_digits = dplaces + 4;
tmp6 = M_get_stack_var();
tmp7 = M_get_stack_var();
tmp8 = M_get_stack_var();
tmp9 = M_get_stack_var();
dplaces += 6 + (int)log10((double)places);
m_apm_copy(tmp7, MM_One);
tmp7->m_apm_exponent = -places;
M_log_AGM_R_func(tmp8, dplaces, MM_One, tmp7);
m_apm_multiply(tmp6, tmp7, MM_0_5);
M_log_AGM_R_func(tmp9, dplaces, MM_One, tmp6);
m_apm_subtract(MM_lc_log2, tmp9, tmp8); /* log(2) */
tmp7->m_apm_exponent -= 1; /* divide by 10 */
M_log_AGM_R_func(tmp9, dplaces, MM_One, tmp7);
m_apm_subtract(MM_lc_log10, tmp9, tmp8); /* log(10) */
m_apm_reciprocal(MM_lc_log10R, dplaces, MM_lc_log10); /* 1 / log(10) */
M_restore_stack(4);
}
}
/****************************************************************************/
/*
* define a notation for a function 'R' :
*
*
*
* 1
* R (a0, b0) = ------------------------------
*
* ----
* \
* \ n-1 2 2
* 1 - | 2 * (a - b )
* / n n
* /
* ----
* n >= 0
*
*
* where a, b are the classic AGM iteration :
*
*
* a = 0.5 * (a + b )
* n+1 n n
*
*
* b = sqrt(a * b )
* n+1 n n
*
*
*
* define a variable 'c' for more efficient computation :
*
* 2 2 2
* c = 0.5 * (a - b ) , c = a - b
* n+1 n n n n n
*
*/
/****************************************************************************/
void M_log_AGM_R_func(M_APM rr, int places, M_APM aa, M_APM bb)
{
M_APM tmp1, tmp2, tmp3, tmp4, tmpC2, sum, pow_2, tmpA0, tmpB0;
int tolerance, dplaces;
tmpA0 = M_get_stack_var();
tmpB0 = M_get_stack_var();
tmpC2 = M_get_stack_var();
tmp1 = M_get_stack_var();
tmp2 = M_get_stack_var();
tmp3 = M_get_stack_var();
tmp4 = M_get_stack_var();
sum = M_get_stack_var();
pow_2 = M_get_stack_var();
tolerance = places + 8;
dplaces = places + 16;
m_apm_copy(tmpA0, aa);
m_apm_copy(tmpB0, bb);
m_apm_copy(pow_2, MM_0_5);
m_apm_multiply(tmp1, aa, aa); /* 0.5 * [ a ^ 2 - b ^ 2 ] */
m_apm_multiply(tmp2, bb, bb);
m_apm_subtract(tmp3, tmp1, tmp2);
m_apm_multiply(sum, MM_0_5, tmp3);
while (TRUE)
{
m_apm_subtract(tmp1, tmpA0, tmpB0); /* C n+1 = 0.5 * [ An - Bn ] */
m_apm_multiply(tmp4, MM_0_5, tmp1); /* C n+1 */
m_apm_multiply(tmpC2, tmp4, tmp4); /* C n+1 ^ 2 */
/* do the AGM */
m_apm_add(tmp1, tmpA0, tmpB0);
m_apm_multiply(tmp3, MM_0_5, tmp1);
m_apm_multiply(tmp2, tmpA0, tmpB0);
m_apm_sqrt(tmpB0, dplaces, tmp2);
m_apm_round(tmpA0, dplaces, tmp3);
/* end AGM */
m_apm_multiply(tmp2, MM_Two, pow_2);
m_apm_copy(pow_2, tmp2);
m_apm_multiply(tmp1, tmpC2, pow_2);
m_apm_add(tmp3, sum, tmp1);
if ((tmp1->m_apm_sign == 0) ||
((-2 * tmp1->m_apm_exponent) > tolerance))
break;
m_apm_round(sum, dplaces, tmp3);
}
m_apm_subtract(tmp4, MM_One, tmp3);
m_apm_reciprocal(rr, places, tmp4);
M_restore_stack(9);
}
/****************************************************************************/

View file

@ -0,0 +1,93 @@
/*
* M_APM - mapm_lg4.c
*
* Copyright (C) 2003 - 2007 Michael C. Ring
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted. Permission to distribute
* the modified code is granted. Modifications are to be distributed by
* using the file 'license.txt' as a template to modify the file header.
* 'license.txt' is available in the official MAPM distribution.
*
* This software is provided "as is" without express or implied warranty.
*/
/*
*
* This file contains the LOG_NEAR_1 function.
*
*/
#include "pgAdmin3.h"
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
/****************************************************************************/
/*
calculate log (1 + x) with the following series:
x
y = ----- ( |y| < 1 )
x + 2
[ 1 + y ] y^3 y^5 y^7
log [-------] = 2 * [ y + --- + --- + --- ... ]
[ 1 - y ] 3 5 7
*/
void M_log_near_1(M_APM rr, int places, M_APM xx)
{
M_APM tmp0, tmp1, tmp2, tmpS, term;
int tolerance, dplaces, local_precision;
long m1;
tmp0 = M_get_stack_var();
tmp1 = M_get_stack_var();
tmp2 = M_get_stack_var();
tmpS = M_get_stack_var();
term = M_get_stack_var();
tolerance = xx->m_apm_exponent - (places + 6);
dplaces = (places + 12) - xx->m_apm_exponent;
m_apm_add(tmp0, xx, MM_Two);
m_apm_divide(tmpS, (dplaces + 6), xx, tmp0);
m_apm_copy(term, tmpS);
m_apm_multiply(tmp0, tmpS, tmpS);
m_apm_round(tmp2, (dplaces + 6), tmp0);
m1 = 3L;
while (TRUE)
{
m_apm_multiply(tmp0, term, tmp2);
if ((tmp0->m_apm_exponent < tolerance) || (tmp0->m_apm_sign == 0))
break;
local_precision = dplaces + tmp0->m_apm_exponent;
if (local_precision < 20)
local_precision = 20;
m_apm_set_long(tmp1, m1);
m_apm_round(term, local_precision, tmp0);
m_apm_divide(tmp0, local_precision, term, tmp1);
m_apm_add(tmp1, tmpS, tmp0);
m_apm_copy(tmpS, tmp1);
m1 += 2;
}
m_apm_multiply(tmp0, MM_Two, tmpS);
m_apm_round(rr, places, tmp0);
M_restore_stack(5); /* restore the 5 locals we used here */
}
/****************************************************************************/

View file

@ -0,0 +1,138 @@
/*
* M_APM - mapm_log.c
*
* Copyright (C) 1999 - 2007 Michael C. Ring
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted. Permission to distribute
* the modified code is granted. Modifications are to be distributed by
* using the file 'license.txt' as a template to modify the file header.
* 'license.txt' is available in the official MAPM distribution.
*
* This software is provided "as is" without express or implied warranty.
*/
/*
*
* This file contains the LOG and LOG10 functions.
*
*/
#include "pgAdmin3.h"
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
/****************************************************************************/
/*
Calls the LOG function. The formula used is :
log10(x) = A * log(x) where A = log (e) [0.43429448190325...]
10
*/
void m_apm_log10(M_APM rr, int places, M_APM aa)
{
int dplaces;
M_APM tmp8, tmp9;
tmp8 = M_get_stack_var();
tmp9 = M_get_stack_var();
dplaces = places + 4;
M_check_log_places(dplaces + 45);
m_apm_log(tmp9, dplaces, aa);
m_apm_multiply(tmp8, tmp9, MM_lc_log10R);
m_apm_round(rr, places, tmp8);
M_restore_stack(2); /* restore the 2 locals we used here */
}
/****************************************************************************/
void m_apm_log(M_APM r, int places, M_APM a)
{
M_APM tmp0, tmp1, tmp2;
int mexp, dplaces;
if (a->m_apm_sign <= 0)
{
M_apm_log_error_msg(M_APM_RETURN, "\'m_apm_log\', Negative argument");
M_set_to_zero(r);
return;
}
tmp0 = M_get_stack_var();
tmp1 = M_get_stack_var();
tmp2 = M_get_stack_var();
dplaces = places + 8;
/*
* if the input is real close to 1, use the series expansion
* to compute the log.
*
* 0.9999 < a < 1.0001
*/
mexp = a->m_apm_exponent;
if (mexp == 0 || mexp == 1)
{
m_apm_subtract(tmp0, a, MM_One);
if (tmp0->m_apm_sign == 0) /* is input exactly 1 ?? */
{
/* if so, result is 0 */
M_set_to_zero(r);
M_restore_stack(3);
return;
}
if (tmp0->m_apm_exponent <= -4)
{
M_log_near_1(r, places, tmp0);
M_restore_stack(3);
return;
}
}
/* make sure our log(10) is accurate enough for this calculation */
/* (and log(2) which is called from M_log_basic_iteration) */
M_check_log_places(dplaces + 25);
if (abs(mexp) <= 3)
{
M_log_basic_iteration(r, places, a);
}
else
{
/*
* use log (x * y) = log(x) + log(y)
*
* here we use y = exponent of our base 10 number.
*
* let 'C' = log(10) = 2.3025850929940....
*
* then log(x * y) = log(x) + ( C * base_10_exponent )
*/
m_apm_copy(tmp2, a);
mexp = tmp2->m_apm_exponent - 2;
tmp2->m_apm_exponent = 2; /* force number between 10 & 100 */
M_log_basic_iteration(tmp0, dplaces, tmp2);
m_apm_set_long(tmp1, (long)mexp);
m_apm_multiply(tmp2, tmp1, MM_lc_log10);
m_apm_add(tmp1, tmp2, tmp0);
m_apm_round(r, places, tmp1);
}
M_restore_stack(3); /* restore the 3 locals we used here */
}
/****************************************************************************/

View file

@ -0,0 +1,131 @@
/*
* M_APM - mapm_mul.c
*
* Copyright (C) 1999 - 2007 Michael C. Ring
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted. Permission to distribute
* the modified code is granted. Modifications are to be distributed by
* using the file 'license.txt' as a template to modify the file header.
* 'license.txt' is available in the official MAPM distribution.
*
* This software is provided "as is" without express or implied warranty.
*/
/*
*
* This file contains basic multiplication function.
*
*/
#include "pgAdmin3.h"
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
extern void M_fast_multiply(M_APM, M_APM, M_APM);
/****************************************************************************/
void m_apm_multiply(M_APM r, M_APM a, M_APM b)
{
int ai, itmp, sign, nexp, ii, jj, indexa, indexb, index0, numdigits;
UCHAR *cp, *cpr, *cp_div, *cp_rem;
void *vp;
sign = a->m_apm_sign * b->m_apm_sign;
nexp = a->m_apm_exponent + b->m_apm_exponent;
if (sign == 0) /* one number is zero, result is zero */
{
M_set_to_zero(r);
return;
}
numdigits = a->m_apm_datalength + b->m_apm_datalength;
indexa = (a->m_apm_datalength + 1) >> 1;
indexb = (b->m_apm_datalength + 1) >> 1;
/*
* If we are multiplying 2 'big' numbers, use the fast algorithm.
*
* This is a **very** approx break even point between this algorithm
* and the FFT multiply. Note that different CPU's, operating systems,
* and compiler's may yield a different break even point. This point
* (~96 decimal digits) is how the test came out on the author's system.
*/
if (indexa >= 48 && indexb >= 48)
{
M_fast_multiply(r, a, b);
return;
}
ii = (numdigits + 1) >> 1; /* required size of result, in bytes */
if (ii > r->m_apm_malloclength)
{
if ((vp = MAPM_REALLOC(r->m_apm_data, (ii + 32))) == NULL)
{
/* fatal, this does not return */
M_apm_log_error_msg(M_APM_FATAL, "\'m_apm_multiply\', Out of memory");
}
r->m_apm_malloclength = ii + 28;
r->m_apm_data = (UCHAR *)vp;
}
M_get_div_rem_addr(&cp_div, &cp_rem);
index0 = indexa + indexb;
cp = r->m_apm_data;
memset(cp, 0, index0);
ii = indexa;
while (TRUE)
{
index0--;
cpr = cp + index0;
jj = indexb;
ai = (int)a->m_apm_data[--ii];
while (TRUE)
{
itmp = ai * b->m_apm_data[--jj];
*(cpr - 1) += cp_div[itmp];
*cpr += cp_rem[itmp];
if (*cpr >= 100)
{
*cpr -= 100;
*(cpr - 1) += 1;
}
cpr--;
if (*cpr >= 100)
{
*cpr -= 100;
*(cpr - 1) += 1;
}
if (jj == 0)
break;
}
if (ii == 0)
break;
}
r->m_apm_sign = sign;
r->m_apm_exponent = nexp;
r->m_apm_datalength = numdigits;
M_apm_normalize(r);
}
/****************************************************************************/

Some files were not shown because too many files have changed in this diff Show more