void printJoins(int numJoins) { uint32_t queryCount = 4 << (4 * numJoins); uint64_t queryConfig = 0; for (queryConfig = 0; queryConfig < queryCount; queryConfig++) { int joinIndex = -1; uint32_t tableType = 0; tableType = queryConfig & 3; printf("SELECT * FROM %s a", TABLE[tableType]); for (joinIndex = 0; joinIndex < numJoins; joinIndex++) { uint32_t joinType = 0; joinType = getJoinType(queryConfig, joinIndex); tableType = getTableType(queryConfig, joinIndex); printf(" %s JOIN %s %c ON (%c.id = %c.id)", JOIN[joinType], TABLE[tableType], 'a' + (joinIndex + 1), 'a' + (joinIndex), 'a' + (joinIndex + 1)); } printf(" ORDER BY 1, 2"); for (joinIndex = 0; joinIndex < numJoins; joinIndex++) { printf(", %d, %d", joinIndex * 2 + 3, joinIndex * 2 + 4); } printf(";\n"); } }
/** * Computes a join or meet type for the given pair of types. The join flag allows to determine * whether the join or meet type is computed. */ TypePtr getJoinMeetType(const TypePtr& typeA, const TypePtr& typeB, bool join) { static const TypePtr fail = 0; // add a structure based algorithm for computing the Join-Type // shortcut for equal types if (*typeA == *typeB) { return typeA; } // the rest depends on the node types NodeType nodeTypeA = typeA->getNodeType(); NodeType nodeTypeB = typeB->getNodeType(); // handle generic types if (nodeTypeA == NT_GenericType && nodeTypeB == NT_GenericType) { // let the join computation handle the case const GenericTypePtr& genTypeA = static_pointer_cast<const GenericType>(typeA); const GenericTypePtr& genTypeB = static_pointer_cast<const GenericType>(typeB); return (join) ? getJoinType(genTypeA, genTypeB) : getMeetType(genTypeA, genTypeB); } // handle vector types (only if array super type of A is a super type of B) // make sure typeA is the vector if (nodeTypeA != NT_VectorType && nodeTypeB == NT_VectorType) { // switch sides return getJoinMeetType(typeB, typeA, join); } // handle vector-array conversion (only works for joins) if (join && nodeTypeA == NT_VectorType) { VectorTypePtr vector = static_pointer_cast<const VectorType>(typeA); // the only potential super type is an array of the same element type IRBuilder builder(vector->getNodeManager()); ArrayTypePtr array = builder.arrayType(vector->getElementType()); if (isSubTypeOf(typeB, array)) { return array; } // no common super type! return fail; } // the rest can only work if it is of the same kind if (nodeTypeA != nodeTypeB) { // => no common super type return fail; } // check for functions if (nodeTypeA == NT_FunctionType) { FunctionTypePtr funTypeA = static_pointer_cast<const FunctionType>(typeA); FunctionTypePtr funTypeB = static_pointer_cast<const FunctionType>(typeB); // check number of arguments auto paramsA = funTypeA->getParameterTypes(); auto paramsB = funTypeB->getParameterTypes(); if (paramsA.size() != paramsB.size()) { // not matching return fail; } // check function kind FunctionKind resKind = funTypeA->getKind(); if (funTypeA->getKind() != funTypeB->getKind()) { // differences are only allowed when going from plain to closure type if ((funTypeA->isPlain() && funTypeB->isClosure()) || (funTypeA->isClosure() && funTypeB->isPlain())) { resKind = FK_CLOSURE; } else { return fail; } } // compute join type // JOIN/MEET result and argument types - if possible TypePtr cur = getJoinMeetType(funTypeA->getReturnType(), funTypeB->getReturnType(), join); TypePtr resType = cur; // continue with parameters TypeList params; for (std::size_t i=0; i<paramsA.size(); i++) { // ATTENTION: this goes in the reverse direction cur = getJoinMeetType(paramsA[i], paramsB[i], !join); // if a pair can not be matched => fail if (!cur) return fail; params.push_back(cur); } // construct resulting type IRBuilder builder(funTypeA->getNodeManager()); return builder.functionType(params, resType, resKind); } // everything else does not have a common join/meet type return fail; }