Here is the source code for a UDF that I wrote (based on Oleg's example: http://www.aginity.com/Blog/tabid/182/PostID/55/Creating-a-Netezza-User-Defined-Function-(UDF).aspx )
SELECT TEST_NVL(null, 'world') returns 'world'
SELECT TEST_NVL('', 'world') returns 'world'
SELECT TEST_NVL('hello', 'world') returns 'hello'
You can use this UDF in the where clause as well:
select a,b from t where upper(trim (TEST_NVL (a, b)))= 'XYZ'
<?xml version="1.0" standalone="yes"?>
<UDXDataSet xmlns="http://aginity.com/NetezzaWorkbench/UDXDataSet.xsd">
<Definition>
<ID>-1</ID>
<Name>TEST_NVL</Name>
<ClassName>CTEST_NVL</ClassName>
<ReturnDataTypeID>32</ReturnDataTypeID>
<ReturnPrecision>255</ReturnPrecision>
<ReturnScale>0</ReturnScale>
<LogMask>3</LogMask>
<Comment />
<SourceCode>
#include "udxinc.h"
#include "udxhelpers.h"
#include "string.h"
using namespace nz::udx::dthelpers;
using namespace nz::udx;
//****************************************************************************
// This is the main Function class implementation
//****************************************************************************
class CTEST_NVL: public Udf
{
public:
static Udf *instantiate();
virtual ReturnValue evaluate();
virtual uint64 calculateSize() const;
private:
// region Property Accessors
inline bool is_arg_null_string1() const
{
return isArgNull(0);
};
inline StringArg* get_arg_string1() const
{
return stringArg(0);
};
inline bool is_arg_null_string2() const
{
return isArgNull(1);
};
inline StringArg* get_arg_string2() const
{
return stringArg(1);
};
// end region
};
//****************************************************************************
// This static function creates a new instance of the class.
Udf *CTEST_NVL::instantiate()
{
return new CTEST_NVL();
}
//****************************************************************************
// Calculates and returns the function result.
ReturnValue CTEST_NVL::evaluate()
{
// find out input string lengths
int len[2];
len[0] = isArgNull(0) ? 0 : stringArg(0)->length;
len[1] = isArgNull(1) ? 0 : stringArg(1)->length;
// create an array that holds input strings
char* *parts = new char*[2];
parts[0] = len[0] == 0 ? NULL : stringArg(0)->data;
parts[1] = len[1] == 0 ? NULL : stringArg(1)->data;
// prepare return value object
StringReturn *pResult = stringReturnInfo();
pResult->data[0] = 0;
char*pCurrent = pResult->data;
// Note: Lengths of the string arguments passed have been set to varchar(255)
// if the first string has a length of 1 or more, copy the first string to the return value
// Could have used strcpy. Included string.h above
if (len[0]>0) {
int m = 0;
int n = len[0] -1;
while (m <= n) {
*pCurrent= parts[0][m];
pCurrent++;
m++;
}
}
else
// return the second string if the first string has zero characters or is NULL.
if (len[0] == 0) {
if (len[1] > 0)
{
int j = 0;
int k = len[1] - 1;
while (j <= k)
{
*pCurrent = parts[1][j];
pCurrent++;
j++;
}
}
}
// clean up
delete []parts;
// specify the output string length
pResult->size = pCurrent - pResult->data;
// done, return the generated NK
NZ_UDX_RETURN_STRING(pResult);
}
//****************************************************************************
// Calculates the size of the return value for generic parameter style (ANY)
uint64 CTEST_NVL::calculateSize() const
{
// TODO: replace zero with an actual return value size
return 0;
}</SourceCode>
<UDXType>0</UDXType>
<TestSQL>
select TEST_NVL('s','world')</TestSQL>
<Language>CPP</Language>
<MemoryUsage />
<Deterministic>true</Deterministic>
<ReturnsNullOnNullInput>false</ReturnsNullOnNullInput>
<AggregateType>0</AggregateType>
<Args>
<ParentID>-1</ParentID>
<Sequence>1</Sequence>
<Name>string1</Name>
<DataTypeID>32</DataTypeID>
<Precision>255</Precision>
<Scale>0</Scale>
<Comment />
</Args>
<Args>
<ParentID>-1</ParentID>
<Sequence>2</Sequence>
<Name>string2</Name>
<DataTypeID>32</DataTypeID>
<Precision>255</Precision>
<Scale>0</Scale>
<Comment />
</Args>
</Definition>
<DataTypes>
<DataTypeID>1</DataTypeID>
<Name>BIGINT</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>2</DataTypeID>
<Name>BOOLEAN</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>3</DataTypeID>
<Name>BPCHAR</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>4</DataTypeID>
<Name>BYTEINT</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>5</DataTypeID>
<Name>CHAR</Name>
<HasPrecision>true</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>6</DataTypeID>
<Name>DATE</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>7</DataTypeID>
<Name>DECIMAL</Name>
<HasPrecision>true</HasPrecision>
<HasScale>true</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>8</DataTypeID>
<Name>DOUBLE</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>9</DataTypeID>
<Name>FLOAT</Name>
<HasPrecision>true</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>10</DataTypeID>
<Name>INTEGER</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>11</DataTypeID>
<Name>INTERVAL DAY</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>12</DataTypeID>
<Name>INTERVAL DAY TO HOUR</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>13</DataTypeID>
<Name>INTERVAL DAY TO MINUTE</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>14</DataTypeID>
<Name>INTERVAL DAY TO SECOND</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>15</DataTypeID>
<Name>INTERVAL HOUR</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>16</DataTypeID>
<Name>INTERVAL HOUR TO MINUTE</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>17</DataTypeID>
<Name>INTERVAL HOUR TO SECOND</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>18</DataTypeID>
<Name>INTERVAL MINUTE</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>19</DataTypeID>
<Name>INTERVAL MINUTE TO SECOND</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>20</DataTypeID>
<Name>INTERVAL MONTH</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>21</DataTypeID>
<Name>INTERVAL SECOND</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>22</DataTypeID>
<Name>INTERVAL YEAR</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>23</DataTypeID>
<Name>INTERVAL YEAR TO MONTH</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>24</DataTypeID>
<Name>NCHAR</Name>
<HasPrecision>true</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>25</DataTypeID>
<Name>NUMERIC</Name>
<HasPrecision>true</HasPrecision>
<HasScale>true</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>26</DataTypeID>
<Name>NVARCHAR</Name>
<HasPrecision>true</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>27</DataTypeID>
<Name>REAL</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>28</DataTypeID>
<Name>SMALLINT</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>29</DataTypeID>
<Name>TIME</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>30</DataTypeID>
<Name>TIMESTAMP</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>31</DataTypeID>
<Name>TIMETZ</Name>
<HasPrecision>false</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
<DataTypes>
<DataTypeID>32</DataTypeID>
<Name>VARCHAR</Name>
<HasPrecision>true</HasPrecision>
<HasScale>false</HasScale>
</DataTypes>
</UDXDataSet>

