static void raiseFunctionFactoryError(const std::string& nameString, int functionId, const std::vector<AbstractExpression*>* args) { char fn_message[1024]; if (args) { snprintf(fn_message, sizeof(fn_message), "Internal Error: SQL function '%s' with ID (%d) with (%d) parameters is not implemented in VoltDB (or may have been incorrectly parsed)", nameString.c_str(), functionId, (int)args->size()); } else { snprintf(fn_message, sizeof(fn_message), "Internal Error: SQL function '%s' with ID (%d) was serialized without its required parameters list.", nameString.c_str(), functionId); } DEBUG_ASSERT_OR_THROW_OR_CRASH(false, fn_message); throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION, fn_message); }
const vector<SchemaColumn*>& AbstractPlanNode::getOutputSchema() const { // Test for a valid output schema defined at this plan node. // 1-or-more column output schemas are always valid. // 0-column output schemas are not currently supported, // but SHOULD be for certain edge cases. // So, leave that door open, at least here. if (m_validOutputColumnCount >= 0) { return m_outputSchema; } // If m_validOutputColumnCount indicates with its magic (negative) value // that this node does not actually define its own output schema, // navigate downward to its first child (normal or inline) that does. // NOTE: we have the option of caching the result in the local m_outputSchema vector // and updating m_validOutputColumnCount but that would involve deep copies or // reference counts or some other memory management scheme. // On the other hand, pass-through output schemas aren't accessed that often // (or at least don't strictly NEED to be). // Best practice is probably to access them only in the executor's init method // and cache any details pertinent to execute. const AbstractPlanNode* parent = this; const AbstractPlanNode* schema_definer = NULL; while (true) { // An inline child projection is an excellent place to find an output schema. if (parent->m_validOutputColumnCount == SCHEMA_UNDEFINED_SO_GET_FROM_INLINE_PROJECTION) { schema_definer = parent->getInlinePlanNode(PLAN_NODE_TYPE_PROJECTION); DEBUG_ASSERT_OR_THROW_OR_CRASH((schema_definer != NULL), "Incorrect output schema source for plannode:\n" << debug("")); DEBUG_ASSERT_OR_THROW_OR_CRASH((schema_definer->m_validOutputColumnCount >= 0), "Missing output schema for inline projection:\n" << debug("")); return schema_definer->m_outputSchema; } // A child node is another possible output schema source, but may take some digging. if (parent->m_validOutputColumnCount == SCHEMA_UNDEFINED_SO_GET_FROM_CHILD) { // Joins always define their own output schema, // so there should only be one child to check, // EXCEPT for unions, which DO follow the convention of using the first child's // output schema, anyway. So, just assert that there is at least one child node to use. DEBUG_ASSERT_OR_THROW_OR_CRASH( ! parent->m_children.empty(), "Incorrect output schema source for plannode:\n" << debug("") ); schema_definer = parent->m_children[0]; DEBUG_ASSERT_OR_THROW_OR_CRASH((schema_definer != NULL), "Incorrect output schema source for plannode:\n" << debug("")); if (schema_definer->m_validOutputColumnCount >= 0) { return schema_definer->m_outputSchema; } // The child is no more an output schema definer than its parent, keep searching. parent = schema_definer; continue; } // All the expected cases have been eliminated -- that can't be good. break; } throwFatalLogicErrorStreamed("No valid output schema defined for plannode:\n" << debug("")); }