void Operator::setFunction(Function *func, unsigned func_type) { //Raises an error if the function type is invalid if(func_type > FUNC_RESTRICT) throw Exception(ERR_REF_FUNCTION_INV_TYPE,__PRETTY_FUNCTION__,__FILE__,__LINE__); else if(func_type==FUNC_OPERATOR) { //Raises an error if the function is not allocated if(!func) throw Exception(Exception::getErrorMessage(ERR_ASG_NOT_ALOC_FUNCTION) .arg(Utf8String::create(this->getName(true))) .arg(BaseObject::getTypeName(OBJ_OPERATOR)), ERR_ASG_NOT_ALOC_FUNCTION,__PRETTY_FUNCTION__,__FILE__,__LINE__); /* Raises an error if the parameter count is invalid. To be used by the operator the function must own 1 or 2 parameters */ else if(func->getParameterCount()==0 || func->getParameterCount() > 2) throw Exception(Exception::getErrorMessage(ERR_ASG_FUNC_INV_PARAM_COUNT) .arg(Utf8String::create(this->getName())) .arg(BaseObject::getTypeName(OBJ_OPERATOR)), ERR_ASG_FUNC_INV_PARAM_COUNT,__PRETTY_FUNCTION__,__FILE__,__LINE__); else { unsigned param_count=func->getParameterCount(); PgSQLType param_type1=PgSQLType("any"), param_type2=PgSQLType("any"); //Get the function parameter to make validations param_type1=func->getParameter(0).getType(); if(param_count==2) param_type2=func->getParameter(1).getType(); //Validates the function parameters according to the operator arguments //ERROR 1: The function have parameters of the type 'any' if((param_type1=="any" || (param_count==2 && param_type2=="any")) || //ERROR 2: The function parameter count is 1 and the type of operator argument is not 'any' (param_count==1 && argument_types[0]!="any" && argument_types[1]!="any") || //ERROR 3: The function parameter count is 2 and the operator arguments is not 'any' (param_count==2 && ((argument_types[0]=="any" && argument_types[1]!="any") || (argument_types[0]!="any" && argument_types[1]=="any"))) || /* ERROR 4: The function parameter count is 2 and the argument types differs from parameters type */ (param_count==2 && ((argument_types[0]=="any" || argument_types[1]=="any") || (argument_types[0]!=param_type1 || argument_types[1]!=param_type2))) || //ERROR 5: When the function has 1 parameter the type differ from the operator argument (param_count==1 && ((argument_types[0]!="any" && argument_types[0]!=param_type1) || (argument_types[1]!="any" && argument_types[1]!=param_type1)))) throw Exception(Exception::getErrorMessage(ERR_ASG_FUNCTION_INV_PARAMS) .arg(Utf8String::create(this->getName())) .arg(BaseObject::getTypeName(OBJ_OPERATOR)), ERR_ASG_FUNCTION_INV_PARAMS,__PRETTY_FUNCTION__,__FILE__,__LINE__); } } functions[func_type]=func; }
Operator::Operator(void) { unsigned i; obj_type=OBJ_OPERATOR; for(i=FUNC_OPERATOR; i <= FUNC_RESTRICT; i++) functions[i]=nullptr; for(i=Operator::OPER_COMMUTATOR; i <= OPER_NEGATOR; i++) operators[i]=nullptr; hashes=merges=false; argument_types[LEFT_ARG]=PgSQLType("any"); argument_types[RIGHT_ARG]=PgSQLType("any"); attributes[ParsersAttributes::LEFT_TYPE]=""; attributes[ParsersAttributes::RIGHT_TYPE]=""; attributes[ParsersAttributes::COMMUTATOR_OP]=""; attributes[ParsersAttributes::NEGATOR_OP]=""; attributes[ParsersAttributes::RESTRICTION_FUNC]=""; attributes[ParsersAttributes::JOIN_FUNC]=""; attributes[ParsersAttributes::OPERATOR_FUNC]=""; attributes[ParsersAttributes::HASHES]=""; attributes[ParsersAttributes::MERGES]=""; attributes[ParsersAttributes::SIGNATURE]=""; attributes[ParsersAttributes::REF_TYPE]=""; }
PgSQLType PgSQLType::getAliasType(void) { if(type_list[this->type_idx]=="serial") return(PgSQLType("integer")); else if(type_list[this->type_idx]=="smallserial") return(PgSQLType("smallint")); else if(type_list[this->type_idx]=="bigserial") return(PgSQLType("bigint")); else return(PgSQLType(type_list[this->type_idx])); }
Function::Function(void) { return_type=PgSQLType(QString("void")); language=nullptr; returns_setof=false; is_wnd_function=false; is_leakproof=false; obj_type=OBJ_FUNCTION; execution_cost=100; row_amount=1000; attributes[ParsersAttributes::PARAMETERS]=QString(); attributes[ParsersAttributes::EXECUTION_COST]=QString(); attributes[ParsersAttributes::ROW_AMOUNT]=QString(); attributes[ParsersAttributes::RETURN_TYPE]=QString(); attributes[ParsersAttributes::FUNCTION_TYPE]=QString(); attributes[ParsersAttributes::LANGUAGE]=QString(); attributes[ParsersAttributes::RETURNS_SETOF]=QString(); attributes[ParsersAttributes::SECURITY_TYPE]=QString(); attributes[ParsersAttributes::BEHAVIOR_TYPE]=QString(); attributes[ParsersAttributes::DEFINITION]=QString(); attributes[ParsersAttributes::SIGNATURE]=QString(); attributes[ParsersAttributes::REF_TYPE]=QString(); attributes[ParsersAttributes::WINDOW_FUNC]=QString(); attributes[ParsersAttributes::RETURN_TABLE]=QString(); attributes[ParsersAttributes::LIBRARY]=QString(); attributes[ParsersAttributes::SYMBOL]=QString(); attributes[ParsersAttributes::LEAKPROOF]=QString(); }
PgSQLType PgSQLType::getAliasType(void) { if(!isUserType()) { if(type_list[this->type_idx]==QString("serial")) return(PgSQLType(QString("integer"))); else if(type_list[this->type_idx]==QString("smallserial")) return(PgSQLType(QString("smallint"))); else if(type_list[this->type_idx]==QString("bigserial")) return(PgSQLType(QString("bigint"))); else return(PgSQLType(type_list[this->type_idx])); } else return(*this); }
void Type::convertFunctionParameters(bool inverse_conv) { unsigned i, conf_funcs[]={ INPUT_FUNC, RECV_FUNC, OUTPUT_FUNC, SEND_FUNC }; Parameter param; Function *func=nullptr; for(i=0; i < 4; i++) { func=functions[conf_funcs[i]]; if(func) { if(conf_funcs[i]==OUTPUT_FUNC || conf_funcs[i]==SEND_FUNC) { param=func->getParameter(0); func->removeParameter(0); if(!inverse_conv) { param.setType(PgSQLType(this)); func->addParameter(param); } else { param.setType(PgSQLType(QString("\"any\""))); func->addParameter(param); } } else if(conf_funcs[i]==INPUT_FUNC || conf_funcs[i]==RECV_FUNC) { if(!inverse_conv) func->setReturnType(PgSQLType(this)); else func->setReturnType(PgSQLType(QString("\"any\""))); } } } setCodeInvalidated(true); }
Sequence::Sequence(void) { obj_type=OBJ_SEQUENCE; cycle=false; setDefaultValues(PgSQLType(QString("serial"))); owner_col=nullptr; attributes[ParsersAttributes::INCREMENT]=QString(); attributes[ParsersAttributes::MIN_VALUE]=QString(); attributes[ParsersAttributes::MAX_VALUE]=QString(); attributes[ParsersAttributes::START]=QString(); attributes[ParsersAttributes::CACHE]=QString(); attributes[ParsersAttributes::CYCLE]=QString(); attributes[ParsersAttributes::OWNER_COLUMN]=QString(); attributes[ParsersAttributes::TABLE]=QString(); attributes[ParsersAttributes::COLUMN]=QString(); }
PgSQLType PgSQLType::parseString(const QString &str) { QString type_str=str.toLower().simplified(), sptype, interv; bool with_tz=false; unsigned len=0, dim=0, srid=0; int prec=-1; int start=-1, end=-1; QStringList value, intervals; PgSQLType type; //Checking if the string contains one of interval types IntervalType::getTypes(intervals); while(!intervals.isEmpty()) { interv=intervals.back(); intervals.pop_back(); start=type_str.indexOf(QRegExp(QString("( )") + interv.toLower())); if(start>=0) { type_str.remove(start, interv.size()+1); break; } else interv.clear(); } //Check if the type contains "with time zone" descriptor with_tz=QRegExp(QString("(.)*(with time zone)(.)*")).exactMatch(type_str); //Removes the timezone descriptor type_str.remove(QRegExp(QString("(with)(out)*( time zone)"))); //Count the dimension of the type and removes the array descriptor dim=type_str.count(QString("[]")); type_str.remove(QString("[]")); //Check if the type is a variable length type, e.g varchar(200) if(QRegExp(QString("(.)+\\(( )*[0-9]+( )*\\)")).indexIn(type_str) >=0) { start=type_str.indexOf('('); end=type_str.indexOf(')', start); len=type_str.mid(start+1, end-start-1).toUInt(); } //Check if the type is a numeric type, e.g, numeric(10,2) else if(QRegExp(QString("(.)+\\(( )*[0-9]+( )*(,)( )*[0-9]+( )*\\)")).indexIn(type_str) >=0) { start=type_str.indexOf('('); end=type_str.indexOf(')', start); value=type_str.mid(start+1, end-start-1).split(','); len=value[0].toUInt(); prec=value[1].toUInt(); } //Check if the type is a spatial type (PostGiS), e.g, geography(POINTZ, 4296) else if(QRegExp(QString("(.)+\\(( )*[a-z]+(( )*(,)( )*[0-9]+( )*)?\\)"), Qt::CaseInsensitive).indexIn(type_str) >=0) { start=type_str.indexOf('('); end=type_str.indexOf(')', start); value=type_str.mid(start+1, end-start-1).split(','); sptype=value[0].toUpper(); if(value.size() > 1) srid=value[1].toUInt(); } //If the string matches one of the regexp above remove the analyzed parts if(start >=0 && end>=0) type_str.remove(start, end-start+1); /* The resultant string must be only the name of the type without [] and (). NOTE: Since the string was converted to lower case at start it's necessary to get it's original form from the input string in order to correctly create the type. */ type_str=str.mid(str.indexOf(type_str, 0, Qt::CaseInsensitive),type_str.length()).trimmed(); try { try { //Creates the type based on the extracted values type=PgSQLType(type_str); } catch(Exception &) { /* In case of error (specially with PostGiS types) split the string to remove the schema name and try to create the type once more */ QStringList typname=type_str.split('.'); if(typname.size()==2) type=PgSQLType(typname[1]); else { /* One last try it to check if the type has an entry on user defined types as pg_catalog.[type name] */ type=PgSQLType(QString("pg_catalog.") + type_str); } } type.setWithTimezone(with_tz); type.setDimension(dim); if(type.isNumericType() && len > 0 && prec >=0) { type.setLength(len); type.setPrecision(prec); } else if(type.isDateTimeType() && len > 0) type.setPrecision(len); else if(type.hasVariableLength() && len > 0) type.setLength(len); if(!interv.isEmpty()) type.setIntervalType(IntervalType(interv)); else if(!sptype.isEmpty()) type.setSpatialType(SpatialType(sptype, srid)); return(type); } catch(Exception &e) { throw Exception(e.getErrorMessage(), e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, str); } }
void TypeWidget::applyConfiguration(void) { try { Type *type=nullptr; unsigned i, count; startConfiguration<Type>(); type=dynamic_cast<Type *>(this->object); BaseObjectWidget::applyConfiguration(); //Configuring an enumaration type if(enumeration_rb->isChecked()) { type->setConfiguration(Type::ENUMERATION_TYPE); count=enumerations_tab->getRowCount(); for(i=0; i < count; i++) type->addEnumeration(enumerations_tab->getCellText(i,0).toUtf8()); } //Configuration a composite type else if(composite_rb->isChecked()) { type->setConfiguration(Type::COMPOSITE_TYPE); count=attributes_tab->getRowCount(); for(i=0; i < count; i++) type->addAttribute(attributes_tab->getRowData(i).value<TypeAttribute>()); } //Configuration a range type else if(range_rb->isChecked()) { type->setConfiguration(Type::RANGE_TYPE); type->setCollation(collation_sel->getSelectedObject()); type->setSubtype(range_subtype->getPgSQLType()); type->setSubtypeOpClass(dynamic_cast<OperatorClass *>(opclass_sel->getSelectedObject())); type->setFunction(Type::CANONICAL_FUNC, dynamic_cast<Function *>(functions_sel[Type::CANONICAL_FUNC]->getSelectedObject())); type->setFunction(Type::SUBTYPE_DIFF_FUNC, dynamic_cast<Function *>(functions_sel[Type::SUBTYPE_DIFF_FUNC]->getSelectedObject())); } //Configuring a base type else { type->setConfiguration(Type::BASE_TYPE); type->setLikeType(like_type->getPgSQLType()); type->setElement(element_type->getPgSQLType()); type->setInternalLength(internal_len_sb->value()); type->setByValue(by_value_chk->isChecked()); type->setPreferred(preferred_chk->isChecked()); type->setCollatable(collatable_chk->isChecked()); if(!delimiter_edt->text().isEmpty()) type->setDelimiter(delimiter_edt->text().at(0).toLatin1()); type->setDefaultValue(default_value_edt->text()); type->setCategory(CategoryType(category_cmb->currentText())); type->setAlignment(PgSQLType(alignment_cmb->currentText())); type->setStorage(StorageType(storage_cmb->currentText())); for(i=Type::INPUT_FUNC; i <= Type::ANALYZE_FUNC; i++) type->setFunction(i, dynamic_cast<Function *>(functions_sel[i]->getSelectedObject())); } finishConfiguration(); } catch(Exception &e) { cancelConfiguration(); throw Exception(e.getErrorMessage(),e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e); } }
void TypeWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Schema *schema, Type *type) { PgSQLType like_tp, elem_tp; unsigned type_conf, i, count; BaseObjectWidget::setAttributes(model, op_list, type, schema); attrib_collation_sel->setModel(model); attrib_type_wgt->setAttributes(PgSQLType(), model); range_subtype->setAttributes(PgSQLType(), model); opclass_sel->setModel(model); for(i=Type::INPUT_FUNC; i <= Type::SUBTYPE_DIFF_FUNC; i++) functions_sel[i]->setModel(model); if(type) { type_conf=type->getConfiguration(); if(type_conf==Type::COMPOSITE_TYPE) { composite_rb->setChecked(true); attributes_tab->blockSignals(true); count=type->getAttributeCount(); for(i=0; i < count; i++) { attributes_tab->addRow(); showAttributeData(type->getAttribute(i),i); } attributes_tab->blockSignals(false); attributes_tab->clearSelection(); } else if(type_conf==Type::ENUMERATION_TYPE) { enumeration_rb->setChecked(true); enumerations_tab->blockSignals(true); count=type->getEnumerationCount(); for(i=0; i < count; i++) { enumerations_tab->addRow(); enumerations_tab->setCellText(type->getEnumeration(i), i, 0); } enumerations_tab->blockSignals(false); enumerations_tab->clearSelection(); } else if(type_conf==Type::RANGE_TYPE) { range_rb->setChecked(true); opclass_sel->setSelectedObject(type->getSubtypeOpClass()); range_subtype->setAttributes(type->getSubtype(), model); functions_sel[Type::CANONICAL_FUNC]->setSelectedObject(type->getFunction(Type::CANONICAL_FUNC)); functions_sel[Type::SUBTYPE_DIFF_FUNC]->setSelectedObject(type->getFunction(Type::SUBTYPE_DIFF_FUNC)); } else { base_type_rb->setChecked(true); like_tp=type->getLikeType(); elem_tp=type->getElement(); internal_len_sb->setValue(type->getInternalLength()); by_value_chk->setChecked(type->isByValue()); preferred_chk->setChecked(type->isPreferred()); collatable_chk->setChecked(type->isCollatable()); delimiter_edt->setText(QString(type->getDelimiter())); default_value_edt->setText(type->getDefaultValue()); category_cmb->setCurrentIndex(category_cmb->findText(~type->getCategory())); storage_cmb->setCurrentIndex(storage_cmb->findText(~type->getStorage())); alignment_cmb->setCurrentIndex(alignment_cmb->findText(~type->getAlignment())); for(i=Type::INPUT_FUNC; i <= Type::ANALYZE_FUNC; i++) functions_sel[i]->setSelectedObject(type->getFunction(i)); } } else selectTypeConfiguration(); like_type->setAttributes(like_tp, model); element_type->setAttributes(elem_tp, model); }