bool PgSQLType::canCastTo(PgSQLType type) { // If the types are the same of belongs to the same category they naturally can be casted if(this->type_idx==type.type_idx || (isCharacterType() && type.isCharacterType()) || (isDateTimeType() && type.isDateTimeType()) || (isNumericType() && type.isNumericType()) || (isNetworkType() && type.isNetworkType()) || //Polymorphics anyarray, anyrange, anynoarray, anyenum to anyelement ((isPolymorphicType() && type==QString("anyelement")) || ((*this)==QString("anyelement") && type.isPolymorphicType())) || //Character to network address ((isCharacterType() || isNetworkType()) && (type.isCharacterType() || type.isNetworkType())) || //Integer to OID ((isIntegerType() || isOIDType()) && (type.isIntegerType() || type.isOIDType())) || //abstime to integer ((((*this)==QString("integer") || (*this)==QString("int4")) && type==QString("abstime")) || (((*this)==QString("abstime") && (type==QString("integer") || type==QString("int4")))))) return(true); return(false); }
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); } }