blob: a0a6f7d40dae2d7bd8e00ddeabaeea59ed3fc352 [file] [log] [blame]
//*****************************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
//*****************************************************************************
#include "PrivMgrComponents.h"
#include "PrivMgrMD.h"
#include "PrivMgrMDTable.h"
#include "PrivMgrComponentOperations.h"
#include "PrivMgrComponentPrivileges.h"
#include <string>
#include <cstdio>
#include "ComSmallDefs.h"
// sqlcli.h included because ExExeUtilCli.h needs it (and does not include it!)
#include "sqlcli.h"
#include "ExExeUtilCli.h"
#include "ComDiags.h"
//#include "ComQueue.h"
// CmpCommon.h contains STMTHEAP declaration
#include "CmpCommon.h"
#include "CmpDDLCatErrorCodes.h"
#include "ComUser.h"
namespace Components
{
// *****************************************************************************
// * Class: MyRow
// * Description: This class represents a row in the COMPONENTS table containing:
// * - UID of the component
// * - ANSI name of the component
// * - if the component is a system component (intrinsic to Trafodion)
// * - Description of the component
// *
// * A component can be uniquely identified by its ANSI name or its UID.
// *****************************************************************************
class MyRow : public PrivMgrMDRow
{
public:
// -------------------------------------------------------------------
// Constructors and destructors:
// -------------------------------------------------------------------
MyRow(std::string tableName)
: PrivMgrMDRow(tableName, COMPONENTS_ENUM),
componentUID_(0)
{ };
MyRow(const MyRow &other)
: PrivMgrMDRow(other)
{
componentUID_ = other.componentUID_;
componentName_ = other.componentName_;
isSystem_ = other.isSystem_;
componentDescription_ = other.componentDescription_;
};
virtual ~MyRow(){};
inline void clear() {componentUID_ = 0;};
bool lookupByName(
const std::string & componentName,
int64_t & componentUID,
bool & isSystem,
std::string & componentDescription);
// -------------------------------------------------------------------
// Data Members:
// -------------------------------------------------------------------
int64_t componentUID_;
std::string componentName_;
std::string componentDescription_;
bool isSystem_;
private:
MyRow();
};
// *****************************************************************************
// * Class: MyTable
// * Description: This class represents the COMPONENTS table containing:
// * - the fully qualified name of the table
// *
// * A component can be uniquely identified by its ANSI name or its UID.
// *****************************************************************************
class MyTable : public PrivMgrMDTable
{
public:
MyTable(
const std::string & tableName,
ComDiagsArea * pDiags)
: PrivMgrMDTable(tableName,COMPONENTS_ENUM, pDiags),
lastRowRead_(tableName)
{};
virtual PrivStatus insert(const PrivMgrMDRow &row);
virtual PrivStatus selectWhereUnique(
const std::string & whereClause,
PrivMgrMDRow & row);
inline void clear() { lastRowRead_.clear(); };
PrivStatus fetchByName(
const std::string & componentName,
MyRow &myRow);
private:
MyTable();
MyRow lastRowRead_;
};
}//End namespace Components
using namespace Components;
// *****************************************************************************
// PrivMgrComponents methods
// *****************************************************************************
// -----------------------------------------------------------------------
// Construct a PrivMgrComponents object for a new component.
// -----------------------------------------------------------------------
PrivMgrComponents::PrivMgrComponents (
const std::string & metadataLocation,
ComDiagsArea * pDiags)
: PrivMgr(metadataLocation,pDiags),
fullTableName_(metadataLocation + ".COMPONENTS"),
myTable_(*(new MyTable(fullTableName_,pDiags)))
{ }
// -----------------------------------------------------------------------
// Copy constructor
// -----------------------------------------------------------------------
PrivMgrComponents::PrivMgrComponents(const PrivMgrComponents &other)
: PrivMgr(other),
myTable_(*new MyTable(fullTableName_,pDiags_))
{
fullTableName_ = other.fullTableName_;
}
// -----------------------------------------------------------------------
// Destructor.
// -----------------------------------------------------------------------
PrivMgrComponents::~PrivMgrComponents()
{
delete &myTable_;
}
// *****************************************************************************
// * *
// * Function: PrivMgrComponents::clear *
// * *
// * This function clears any cache associated with this object. *
// * *
// *****************************************************************************
void PrivMgrComponents::clear()
{
MyTable &myTable = static_cast<MyTable &>(myTable_);
myTable.clear();
}
//*********************** End of PrivMgrComponents::clear **********************
// *****************************************************************************
// * *
// * Function: PrivMgrComponents::describeComponents *
// * *
// * lookup "PRIVMGR_MD".COMPONENTS *
// * using the specified component name(unique), *
// * and generate a REGISTER COMPONENT statement, *
// * return component UID. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <componentName> const std::string & In *
// * Unique component name. *
// * *
// * <componentUIDString> std::string & Out *
// * Component UID in string of the specified component name. *
// * *
// * <componentUID> int64_t Out *
// * Component UID of the specified component name. *
// * *
// * <outlines> std::vector<std::string> Out *
// * Output lines in a string array. *
// * *
// *****************************************************************************
// * *
// * Returns: PrivStatus *
// * *
// * *
// *****************************************************************************
PrivStatus PrivMgrComponents::describeComponents(
const std::string & componentName,
std::string & componentUIDString,
int64_t & componentUID,
std::vector<std::string> & outlines)
{
bool isSystem;
std::string detailStr;
std::string componentText;
PrivStatus privStatus = fetchByName(componentName, componentUIDString, componentUID, isSystem, detailStr);
if(privStatus == STATUS_GOOD)
{
componentText += "REGISTER COMPONENT ";
componentText += componentName;
componentText += isSystem?" SYSTEM":"";
componentText += (!detailStr.empty())?" DETAIL '"+detailStr + "';":";";
outlines.push_back(componentText);
outlines.push_back("");
}
return privStatus;
}
//**************** End of PrivMgrComponents::describeComponents ****************
// *****************************************************************************
// * *
// * Function: PrivMgrComponents::dropAll *
// * *
// * This function removes all components from the system. *
// * *
// *****************************************************************************
// * *
// * Returns: PrivStatus *
// * *
// * STATUS_GOOD: All components were deleted. *
// * STATUS_ERROR: Execution failed. A CLI error is put into the diags area. *
// * *
// *****************************************************************************
PrivStatus PrivMgrComponents::dropAll()
{
PrivMgrComponentOperations componentOperations(metadataLocation_,pDiags_);
PrivStatus privStatus = STATUS_GOOD;
// Function dropAll() also drops any privileges granted on
// those operations.
privStatus = componentOperations.dropAll();
if (privStatus != STATUS_GOOD)
{
if (pDiags_->getNumber(DgSqlCode::ERROR_) == 0)
PRIVMGR_INTERNAL_ERROR("Unable to drop operations for component");
return STATUS_ERROR;
}
// If there were any operations or granted privileges on any component, they
// are now gone. Delete all components from the COMPONENTS table.
std::string whereClause(" ");
MyTable &myTable = static_cast<MyTable &>(myTable_);
return myTable_.deleteWhere(whereClause);
}
//********************* End of PrivMgrComponents::dropAll **********************
// *****************************************************************************
// * *
// * Function: PrivMgrComponents::exists *
// * *
// * This function determines if a specific component has been defined in *
// * Privilege Manager metadata. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <componentName> const std::string & In *
// * is the name of the component. Name is assumed to be upper case. *
// * *
// *****************************************************************************
// * *
// * Returns: bool *
// * *
// * true: Component is registered. *
// * false: Component is not registered or error encountered. *
// * *
// *****************************************************************************
bool PrivMgrComponents::exists(const std::string & componentName)
{
MyRow row(fullTableName_);
MyTable &myTable = static_cast<MyTable &>(myTable_);
PrivStatus privStatus = myTable.fetchByName(componentName,row);
if (privStatus == STATUS_GOOD || privStatus == STATUS_WARNING)
return true;
return false;
}
//*********************** End of PrivMgrComponents::exists *********************
// *****************************************************************************
// * *
// * Function: PrivMgrComponents::fetchByName *
// * *
// * Reads and returns data in row associated with a specified *
// * component name. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <componentName> const std::string & In *
// * is the name of the component. Name is assumed to be upper case. *
// * *
// * <componentUIDString> std::string & Out *
// * passes back the unique ID associated with the component as a string. *
// * *
// * <componentUID> int64_t & Out *
// * passes back the unique ID associated with the component as a number. *
// * *
// * <isSystem> bool & Out *
// * passes back true if the component is a system component, otherwise *
// * false is passed back. *
// * *
// * <componentDescription> std::string & Out *
// * passes back the description of the component. Note, providing a *
// * description is optional when the component is registered, so the *
// * value may be empty. *
// * *
// *****************************************************************************
// * *
// * Returns: PrivStatus *
// * *
// * STATUS_GOOD: Found name, UID returned. *
// * STATUS_NOTFOUND: Name not found or error encountered. *
// * *
// *****************************************************************************
PrivStatus PrivMgrComponents::fetchByName(
const std::string & componentName,
std::string & componentUIDString,
int64_t & componentUID,
bool & isSystem,
std::string & componentDescription)
{
MyRow row(fullTableName_);
MyTable &myTable = static_cast<MyTable &>(myTable_);
PrivStatus privStatus = myTable.fetchByName(componentName,row);
if (privStatus == STATUS_NOTFOUND || privStatus == STATUS_ERROR)
return STATUS_NOTFOUND;
componentUIDString = UIDToString(row.componentUID_);
componentUID = row.componentUID_;
isSystem = row.isSystem_;
componentDescription = row.componentDescription_;
return STATUS_GOOD;
}
//******************** End of PrivMgrComponents::fetchByName *******************
// *****************************************************************************
// * *
// * Function: PrivMgrComponents::getCount *
// * *
// * Returns the number of registered components. *
// * *
// *****************************************************************************
// * *
// * Returns: int64_t *
// * *
// * Returns the number of registered components. *
// * *
// *****************************************************************************
int64_t PrivMgrComponents::getCount()
{
std::string whereClause(" ");
int64_t rowCount = 0;
MyTable &myTable = static_cast<MyTable &>(myTable_);
// set pointer in diags area
int32_t diagsMark = pDiags_->mark();
PrivStatus privStatus = myTable.selectCountWhere(whereClause,rowCount);
if (privStatus != STATUS_GOOD)
pDiags_->rewind(diagsMark);
return rowCount;
}
//********************* End of PrivMgrComponents::getCount *********************
// *****************************************************************************
// * *
// * Function: PrivMgrComponents::getUniqueID *
// * *
// * Finds the highest current unique ID and return the next value. *
// * *
// *****************************************************************************
// * *
// * Returns: int64_t *
// * *
// * 0: Error, could not get highest current UID, cannot determine a *
// * unique value to use. *
// * >0: A value guaranteed to be unique in the COMPONENTS table. *
// * *
// * *
// *****************************************************************************
int64_t PrivMgrComponents::getUniqueID()
{
Lng32 len = 0;
char stmtBuf[1000];
strcpy(stmtBuf,"SELECT NVL(MAX(component_uid),0) FROM ");
strcat(stmtBuf,fullTableName_.c_str());
int64_t maxValue = 0;
ExeCliInterface cliInterface(STMTHEAP);
Lng32 cliRC = cliInterface.executeImmediate(stmtBuf,(char *)&maxValue,&len,false);
if (cliRC != 0)
{
return 0;
}
return ++maxValue;
}
//******************** End of PrivMgrComponents::getUniqueID *******************
// *****************************************************************************
// * *
// * Function: PrivMgrComponents::registerComponent *
// * *
// * Adds a row to the COMPONENTS table. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <componentName> const std::string & In *
// * is the name of the component. Name is assumed to be upper case. *
// * *
// * <isSystem> const bool In *
// * is true if this is a system level component, false otherwise. If a *
// * component is system level, Trafodion software assumes is it defined. *
// * System components may only be unregistered by DB__ROOT. Only DB__ROOT *
// * may register a system component (unless a component privilege is added *
// * to authorize the operation). *
// * *
// * <componentDescription> const std::string & In *
// * is a description of the component. *
// * *
// * <existsErrorOK> const bool [In] *
// * if true, exists errors are silently ignored. *
// * *
// *****************************************************************************
// * *
// * Returns: PrivStatus *
// * *
// * STATUS_GOOD: Component name was registered. *
// * *: Unable to register component name, see diags. *
// * *
// *****************************************************************************
PrivStatus PrivMgrComponents::registerComponent(
const std::string & componentName,
const bool isSystem,
const std::string & componentDescription,
const bool existsErrorOK)
{
//TODO: Could check for setting isSystem, could be separate
// privilege, or restricted to DB__ROOT.
PrivMgrComponentPrivileges componentPrivileges(metadataLocation_, pDiags_);
if (!ComUser::isRootUserID()&&
!componentPrivileges.hasSQLPriv(ComUser::getCurrentUser(), SQLOperation::MANAGE_COMPONENTS, true))
{
*pDiags_ << DgSqlCode(-CAT_NOT_AUTHORIZED);
return STATUS_ERROR;
}
// Is component already registered?
if (exists(componentName))
{
if (existsErrorOK)
return STATUS_GOOD;
*pDiags_ << DgSqlCode(-CAT_TABLE_ALREADY_EXISTS)
<< DgTableName(componentName.c_str());
return STATUS_ERROR;
}
// Set up new component entry
int64_t uid = getUniqueID();
if (uid == 0)
return STATUS_ERROR;
MyRow row(fullTableName_);
row.componentUID_ = uid;
row.componentName_ = componentName;
row.isSystem_ = isSystem;
row.componentDescription_ = componentDescription;
// write the row to the components table
return myTable_.insert(row);
}
//***************** End of PrivMgrComponents::registerComponent ****************
// *****************************************************************************
// * *
// * Function: PrivMgrComponents::registerComponentInternal *
// * *
// * Internal function to register a component. No checks are made prior *
// * to inserting row into the COMPONENTS table. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <componentName> const std::string & In *
// * is the name of the component. Name is assumed to be upper case. *
// * *
// * <componentUID> const int64_t In *
// * is a unique ID for the component. *
// * *
// * <isSystem> const bool In *
// * is true if this is a system level component, false otherwise. *
// * *
// * <componentDescription> const std::string & In *
// * is a description of the component. *
// * *
// *****************************************************************************
// * *
// * Returns: PrivStatus *
// * *
// * STATUS_GOOD: Component name was registered. *
// * *: Unable to register component name, see diags. *
// * *
// *****************************************************************************
PrivStatus PrivMgrComponents::registerComponentInternal(
const std::string & componentName,
const int64_t componentUID,
const bool isSystem,
const std::string & componentDescription)
{
MyRow row(fullTableName_);
row.componentUID_ = componentUID;
row.componentName_ = componentName;
row.isSystem_ = isSystem;
row.componentDescription_ = componentDescription;
// write the row to the components table
return myTable_.insert(row);
}
//************* End of PrivMgrComponents::registerComponentInternal ************
// *****************************************************************************
// * *
// * Function: PrivMgrComponents::unregisterComponent *
// * *
// * Removes component from the COMPONENTS table and removes all operations *
// * associated with the component and any granted privileges related to the *
// * component. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <componentName> const std::string & In *
// * is the name of the component. Name is assumed to be upper case. *
// * *
// * <dropBehavior> PrivDropBehavior In *
// * indicates whether restrict or cascade behavior is requested. *
// * *
// *****************************************************************************
// * *
// * Returns: PrivStatus *
// * *
// * STATUS_GOOD: Component was unregistered. *
// * *: Unable to unregister component, see diags. *
// * *
// *****************************************************************************
PrivStatus PrivMgrComponents::unregisterComponent(
const std::string & componentName,
PrivDropBehavior dropBehavior)
{
//TODO: Related, could check below for unregistering system level components.
PrivMgrComponentPrivileges componentPrivileges(metadataLocation_, pDiags_);
if (!ComUser::isRootUserID()&&
!componentPrivileges.hasSQLPriv(ComUser::getCurrentUser(), SQLOperation::MANAGE_COMPONENTS, true))
{
*pDiags_ << DgSqlCode(-CAT_NOT_AUTHORIZED);
return STATUS_ERROR;
}
if (!exists(componentName))
{
*pDiags_ << DgSqlCode(-CAT_TABLE_DOES_NOT_EXIST_ERROR)
<< DgTableName(componentName.c_str());
return STATUS_ERROR;
}
std::string componentUIDString;
int64_t componentUID;
bool isSystem;
std::string tempStr;
fetchByName(componentName,componentUIDString,componentUID,isSystem,tempStr);
//TODO: check authority if it is a system component
PrivMgrComponentOperations componentOperations(metadataLocation_,pDiags_);
PrivStatus privStatus = STATUS_GOOD;
if (dropBehavior == PrivDropBehavior::RESTRICT)
{
if (componentOperations.isComponentUsed(componentUIDString))
{
*pDiags_ << DgSqlCode(-CAT_DEPENDENT_OBJECTS_EXIST);
return STATUS_ERROR;
}
}
else //CASCADE
{
// Function dropAll() also drops any privileges granted on
// those operations.
privStatus = componentOperations.dropAll(componentUIDString);
if (privStatus != STATUS_GOOD)
{
if (pDiags_->getNumber(DgSqlCode::ERROR_) == 0)
PRIVMGR_INTERNAL_ERROR("Unable to drop operations for component");
return STATUS_ERROR;
}
}
// If there were any operations or granted privileges on this component, they
// are now gone. Delete the component from the COMPONENTS table.
std::string whereClause("WHERE COMPONENT_NAME = '");
whereClause += componentName;
whereClause += "'";
return myTable_.deleteWhere(whereClause);
}
//*************** End of PrivMgrComponents::unregisterComponent ****************
// *****************************************************************************
// MyRow methods
// *****************************************************************************
// *****************************************************************************
// * *
// * Function: MyRow::lookupByName *
// * *
// * Looks for a specified component name in cache, and if found, returns *
// * associated data. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <componentName> const std::string & In *
// * is the name of the component. Name is assumed to be upper case. *
// * *
// * <componentUID> int64_t & Out *
// * passes back the unique ID associated with the component. *
// * *
// * <isSystem> bool & Out *
// * passes back true if the component is a system component, otherwise *
// * false is passed back. *
// * *
// * <componentDescription> std::string & Out *
// * passes back the description of the component. Note, providing a *
// * description is optional when the component is registered, so the *
// * value may be empty. *
// * *
// *****************************************************************************
// * *
// * Returns: bool *
// * *
// * true: Component name found in cache. *
// * false: Component name not found in cache. *
// * *
// *****************************************************************************
bool MyRow::lookupByName(
const std::string & componentName,
int64_t & componentUID,
bool & isSystem,
std::string & componentDescription)
{
// If componentUID_ is zero, that means data is uninitialized.
if (componentUID_ == 0 || componentName != componentName_)
return false;
componentUID = componentUID_;
isSystem = isSystem_;
componentDescription = componentDescription_;
return true;
}
//*********************** End of MyRow::lookupByName ***************************
// *****************************************************************************
// MyTable methods
// *****************************************************************************
// *****************************************************************************
// * *
// * Function: MyTable::fetchByName *
// * *
// * Reads from the COMPONENTS table and returns the row associated with *
// * a specified component name. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <componentName> const std::string & In *
// * is the name of the component. Name is assumed to be upper case. *
// * *
// * <row> MyRow & Out *
// * passes back a reference to MyRow, containing the data read. *
// * *
// *****************************************************************************
// * *
// * Returns: PrivStatus *
// * *
// * STATUS_GOOD: Found name, row returned. *
// * *: Name not found or error encountered. *
// * *
// *****************************************************************************
PrivStatus MyTable::fetchByName(
const std::string & componentName,
MyRow & row)
{
// Check the last row read before reading metadata.
if (lastRowRead_.lookupByName(componentName,row.componentUID_,
row.isSystem_,row.componentDescription_))
return STATUS_GOOD;
// Not found in cache, look for the component name in metadata.
std::string whereClause ("WHERE COMPONENT_NAME = '");
whereClause += componentName; //TODO: is character set OK? Do we need to do anything to make sure?
whereClause += "'"; // For instance, prefix with _UTF8?
PrivStatus privStatus = selectWhereUnique(whereClause,row);
switch (privStatus)
{
// Return status to caller to handle
case STATUS_NOTFOUND:
case STATUS_ERROR:
return privStatus;
break;
// Object exists - break out and continue
case STATUS_GOOD:
case STATUS_WARNING:
return STATUS_GOOD;
break;
// Should not occur, internal error
default:
PRIVMGR_INTERNAL_ERROR("Switch statement in PrivMgrComponents::MyTable::fetchByName()");
return STATUS_ERROR;
break;
}
return STATUS_GOOD;
}
//********************** End of MyTable::fetchByName ***************************
// *****************************************************************************
// * *
// * Function: MyTable::insert *
// * *
// * Inserts a row into the COMPONENTS table. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <rowIn> const PrivMgrMDRow & In *
// * is a MyRow to be inserted. *
// * *
// *****************************************************************************
// * *
// * Returns: PrivStatus *
// * *
// * STATUS_GOOD: Row inserted. *
// * *: Insert failed. A CLI error is put into the diags area. *
// * *
// *****************************************************************************
PrivStatus MyTable::insert(const PrivMgrMDRow & rowIn)
{
char insertStatement[1000];
const MyRow & row = static_cast<const MyRow &>(rowIn);
char isSystem[3] = {0};
if (row.isSystem_)
isSystem[0] = 'Y';
else
isSystem[0] = 'N';
sprintf(insertStatement, "insert into %s values (%ld, '%s', '%s', '%s')",
tableName_.c_str(),
row.componentUID_,
row.componentName_.c_str(),
isSystem,
row.componentDescription_.c_str());
return CLIImmediate(insertStatement);
}
//************************** End of MyTable::insert ****************************
// *****************************************************************************
// * *
// * Function: MyTable::selectWhereUnique *
// * *
// * Selects a row from the COMPONENTS table based on the specified *
// * WHERE clause. *
// * *
// *****************************************************************************
// * *
// * Parameters: *
// * *
// * <whereClause> const std::string & In *
// * is the WHERE clause specifying a unique row. *
// * *
// * <rowOut> PrivMgrMDRow & Out *
// * passes back a MyRow. *
// * *
// *****************************************************************************
// * *
// * Returns: PrivStatus *
// * *
// * STATUS_GOOD: Row returned. *
// * *: Select failed. A CLI error is put into the diags area. *
// * *
// *****************************************************************************
PrivStatus MyTable::selectWhereUnique(
const std::string & whereClause,
PrivMgrMDRow & rowOut)
{
// Generate the select statement
std::string selectStmt ("SELECT COMPONENT_UID, COMPONENT_NAME, IS_SYSTEM, COMPONENT_DESCRIPTION FROM ");
selectStmt += tableName_;
selectStmt += " ";
selectStmt += whereClause;
ExeCliInterface cliInterface(STMTHEAP);
PrivStatus privStatus = CLIFetch(cliInterface,selectStmt);
if (privStatus != STATUS_GOOD && privStatus != STATUS_WARNING)
return privStatus;
// Row read successfully. Extract the columns.
char * ptr = NULL;
Lng32 len = 0;
char value[500];
MyRow & row = static_cast<MyRow &>(rowOut);
// column 1: component_uid
cliInterface.getPtrAndLen(1,ptr,len);
row.componentUID_ = *(reinterpret_cast<int64_t*>(ptr));
// column 2: component_name
cliInterface.getPtrAndLen(2,ptr,len);
strncpy(value,ptr,len);
value[len] = 0;
row.componentName_ = value;
// column 3: is_system
cliInterface.getPtrAndLen(3,ptr,len);
strncpy(value,ptr,len);
value[len] = 0;
if (value[0] == 'Y')
row.isSystem_ = true;
else
row.isSystem_ = false;
// column 4: component_description
cliInterface.getPtrAndLen(4,ptr,len);
strncpy(value, ptr,len);
value[len] = 0;
row.componentDescription_ = value;
lastRowRead_ = row;
return STATUS_GOOD;
}
//******************* End of MyTable::selectWhereUnique ************************