/* Copyright (C) 2014 InfiniDB, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /**************************************************************************** * $Id: func_inet_ntoa.cpp 3495 2013-01-21 14:09:51Z rdempsey $ * * ****************************************************************************/ #include #include #include // included when debugging #include #include #include "functor_str.h" #include "calpontsystemcatalog.h" #include "functioncolumn.h" #include "joblisttypes.h" #include "rowgroup.h" namespace funcexp { //------------------------------------------------------------------------------ // The only accessor function that appears to make sense in conjunction with // inet_ntoa() is getStrVal(). I tested in MySQL (outside infinidb), and // comparing inet_ntoa(col) to anything other than a string "seemed" to return // an empty set. So I implemented the other get functions to return a null. // // Later, Daniel found that if you compare inet_ntoa(col) to an integer (ex: 1) // or a double (ex: 1.1), that the getDoubleVal() version of inet_ntoa(col), // will get called. As stated in previous paragraph, I thought I tested this, // but I apparently overlooked something. So getIntVal() and getDoubleVal() // are now implemented. //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // Return input argument type. // See mcs_add in udfsdk.h for explanation of this function. //------------------------------------------------------------------------------ execplan::CalpontSystemCatalog::ColType Func_inet_ntoa::operationType( FunctionParm& fp, execplan::CalpontSystemCatalog::ColType& resultType) { return fp[0]->data()->resultType(); // input type } //------------------------------------------------------------------------------ // Return IP address as a long long int value. // Not sure this is ever called, but emulated getDoubleVal() implementation, // to be safe. (See getDoubleVal() description) //------------------------------------------------------------------------------ int64_t Func_inet_ntoa::getIntVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct) { // std::cout << "In Func_inet_ntoa::getIntVal" << std::endl; std::string sValue = getStrVal(row, fp, isNull, op_ct); int64_t iValue = joblist::NULL_INT64; if (!isNull) { unsigned int newLength = sValue.length(); std::string::size_type dot1 = sValue.find('.'); if (dot1 != std::string::npos) { newLength = dot1; } if (newLength != sValue.length()) sValue.resize(newLength); std::istringstream iss(sValue); iss >> iValue; } return iValue; } //------------------------------------------------------------------------------ // Return IP address as a double value. // SELECT ... WHERE inet_ntoa(ipstring) = 1.1 will call getDoubleVal() // SELECT ... WHERE inet_ntoa(ipstring) = 1 will also call getDoubleVal() //------------------------------------------------------------------------------ double Func_inet_ntoa::getDoubleVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct) { // std::cout << "In Func_inet_ntoa::getDoubleVal" << std::endl; std::string sValue = getStrVal(row, fp, isNull, op_ct); double dValue = doubleNullVal(); if (!isNull) { unsigned int newLength = sValue.length(); std::string::size_type dot1 = sValue.find('.'); if ((dot1 != std::string::npos) && (sValue.length() > dot1 + 1)) { std::string::size_type dot2 = sValue.find('.', dot1 + 1); if (dot2 != std::string::npos) { newLength = dot2; } } if (newLength != sValue.length()) sValue.resize(newLength); std::istringstream iss(sValue); iss >> dValue; } return dValue; } //------------------------------------------------------------------------------ // Return IP address as a string value. // This is the get function that makes sense to use. //------------------------------------------------------------------------------ std::string Func_inet_ntoa::getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct) { // std::cout << "In Func_inet_ntoa::getStrVal" << std::endl; std::string sValue; int64_t iValue = 0; // @bug 3628 reopened: get double and round up, if necessary; // else just get integer value if ((fp[0]->data()->resultType().colDataType == execplan::CalpontSystemCatalog::DECIMAL) || (fp[0]->data()->resultType().colDataType == execplan::CalpontSystemCatalog::UDECIMAL) || (fp[0]->data()->resultType().colDataType == execplan::CalpontSystemCatalog::FLOAT) || (fp[0]->data()->resultType().colDataType == execplan::CalpontSystemCatalog::DOUBLE)) { double d = fp[0]->data()->getDoubleVal(row, isNull); if (d >= 0.0) iValue = (int64_t)(d + 0.5); else iValue = (int64_t)(d - 0.5); } else { iValue = fp[0]->data()->getIntVal(row, isNull); } if (!isNull) { // @bug 3628 reopened: add check for out of range values if ((iValue < 0) || (iValue > UINT_MAX)) isNull = true; else convertNtoa(iValue, sValue); } return sValue; } //------------------------------------------------------------------------------ // Return IP address as a boolean. // N/A so returning null. See explanation at the top of this source file. //------------------------------------------------------------------------------ bool Func_inet_ntoa::getBoolVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct) { // std::cout << "In Func_inet_ntoa::getBoolVal" << std::endl; bool bValue = false; isNull = true; return bValue; } //------------------------------------------------------------------------------ // Return IP address as a decimal value. // N/A so returning null. See explanation at the top of this source file. //------------------------------------------------------------------------------ execplan::IDB_Decimal Func_inet_ntoa::getDecimalVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct) { // IDB_Decimal dValue = fp[0]->data()->getDecimalVal(row, isNull); execplan::IDB_Decimal dValue(joblist::NULL_INT64, 0, 0); isNull = true; return dValue; } //------------------------------------------------------------------------------ // Return IP address as a date. // N/A so returning null. See explanation at the top of this source file. //------------------------------------------------------------------------------ int32_t Func_inet_ntoa::getDateIntVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct) { // std::cout << "In Func_inet_ntoa::getDateIntVal" << std::endl; // int32_t iValue = fp[0]->data()->getDateIntVal(row, isNull); int32_t iValue = joblist::DATENULL; isNull = true; return iValue; } //------------------------------------------------------------------------------ // Return IP address as a date/time. // N/A so returning null. See explanation at the top of this source file. //------------------------------------------------------------------------------ int64_t Func_inet_ntoa::getDatetimeIntVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct) { // std::cout << "In Func_inet_ntoa::getDatetimeVal" << std::endl; // int64t iValue = fp[0]->data()->getDatetimeIntVal(row, isNull); int64_t iValue = joblist::DATETIMENULL; isNull = true; return iValue; } int64_t Func_inet_ntoa::getTimestampIntVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct) { // std::cout << "In Func_inet_ntoa::getTimestampVal" << std::endl; // int64t iValue = fp[0]->data()->getTimestampIntVal(row, isNull); int64_t iValue = joblist::TIMESTAMPNULL; isNull = true; return iValue; } int64_t Func_inet_ntoa::getTimeIntVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct) { // std::cout << "In Func_inet_ntoa::getTimeVal" << std::endl; // int64t iValue = fp[0]->data()->getTimeIntVal(row, isNull); int64_t iValue = joblist::TIMENULL; isNull = true; return iValue; } //------------------------------------------------------------------------------ // Convert an integer IP address to its equivalent IP address string. // Source code based on MySQL source (Item_func_inet_ntoa() in item_strfunc.cc). //------------------------------------------------------------------------------ void Func_inet_ntoa::convertNtoa(int64_t ipNum, std::string& ipString) { struct sockaddr_in sa; sa.sin_addr.s_addr = htonl(ipNum); // now get it back and print it char str[INET_ADDRSTRLEN]; ipString = inet_ntop(AF_INET, &(sa.sin_addr), str, INET_ADDRSTRLEN); } } // namespace funcexp