Example #1
0
void ModelExportHelper::updateProgress(int prog, QString object_id, unsigned obj_type)
{
	int aux_prog=progress + (prog/progress);
	sql_gen_progress=prog;
	if(aux_prog > 100) aux_prog=100;
	emit s_progressUpdated(aux_prog, object_id, static_cast<ObjectType>(obj_type));
}
Example #2
0
void ModelExportHelper::exportToSQL(DatabaseModel *db_model, const QString &filename, const QString &pgsql_ver)
{
	if(!db_model)
		throw Exception(ERR_ASG_NOT_ALOC_OBJECT,__PRETTY_FUNCTION__,__FILE__,__LINE__);

	connect(db_model, SIGNAL(s_objectLoaded(int,QString,uint)), this, SLOT(updateProgress(int,QString,uint)));

	try
	{
		progress=sql_gen_progress=0;
		SchemaParser::setPgSQLVersion(pgsql_ver);
		emit s_progressUpdated(progress,
													 trUtf8("PostgreSQL %1 version code generation...").arg(SchemaParser::getPgSQLVersion()),
													 OBJ_DATABASE);
		progress=1;
		db_model->saveModel(filename, SchemaParser::SQL_DEFINITION);

		emit s_exportFinished();
	}
	catch(Exception &e)
	{
		disconnect(db_model, nullptr, this, nullptr);
		throw Exception(e.getErrorMessage(), e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
	}

	disconnect(db_model, nullptr, this, nullptr);
}
Example #3
0
void ModelExportHelper::undoDBMSExport(DatabaseModel *db_model, Connection &conn)
{
 QString drop_cmd=QString("DROP %1 %2;");
 ObjectType types[]={OBJ_ROLE, OBJ_TABLESPACE};
 int type_id;
 BaseObject *object=nullptr;

 //In case of error during the export all created object are removed
 if(db_created || created_objs[OBJ_ROLE] >= 0 || created_objs[OBJ_TABLESPACE] >= 0)
 {
	 emit s_progressUpdated(100, trUtf8("Destroying created objects..."));

	 //Dropping the database
	 if(db_created)
		 conn.executeDDLCommand(drop_cmd.arg(db_model->getSQLName()).arg(db_model->getName(true)));

	 //Drop the roles / tablespaces created
	 for(type_id=1; type_id >=0; type_id--)
	 {
		 while(created_objs[types[type_id]] >= 0)
		 {
			 object=db_model->getObject(created_objs[types[type_id]], types[type_id]);

			 try
			 {
				 if(!object->isSQLDisabled())
					 conn.executeDDLCommand(drop_cmd.arg(object->getSQLName()).arg(object->getName(true)));
			 }
			 catch(Exception &e){}

			 created_objs[types[type_id]]--;
		 }
	 }
 }
}
void ModelExportHelper::updateProgress(int prog, QString object_id, unsigned)
{
	int aux_prog=progress + (prog/progress);
	sql_gen_progress=prog;
	if(aux_prog > 100) aux_prog=100;
	emit s_progressUpdated(aux_prog, object_id);
}
void ModelValidationHelper::emitValidationFinished(void)
{
	export_thread->quit();

	/* Indicates the model invalidation only when there are validation warnings (broken refs. or no unique name)
	sql errors are ignored since validator cannot fix SQL related problems */
	db_model->setInvalidated(error_count > 0);
	emit s_validationFinished();

	progress=100;
	emit s_progressUpdated(progress,"");
}
Example #6
0
void ModelExportHelper::exportToPNG(ObjectsScene *scene, const QString &filename, float zoom, bool show_grid, bool show_delim)
{
	if(!scene)
		throw Exception(ERR_ASG_NOT_ALOC_OBJECT,__PRETTY_FUNCTION__,__FILE__,__LINE__);

	try
	{
		QPixmap pix;
		QRectF ret=scene->itemsBoundingRect();
		bool shw_grd, shw_dlm, align_objs;
		QGraphicsView viewp(scene);
		QRect retv;
		QPolygon pol;

		//Clear the object scene selection to avoid drawing the selectoin rectangle of the objects
		scene->clearSelection();

		//Make a backup of the current scene options
		ObjectsScene::getGridOptions(shw_grd, align_objs, shw_dlm);

		//Sets the options passed by the user
		ObjectsScene::setGridOptions(show_grid, false, show_delim);

		//Updates the scene to apply the change on grid and delimiter
		scene->update();

		//Configures the viewport alignment to top-left coordinates.
		viewp.setAlignment(Qt::AlignLeft | Qt::AlignTop);

		//Apply the zoom factor on the viewport
		viewp.resetTransform();
		viewp.centerOn(0,0);
		viewp.scale(zoom, zoom);

		//Convert the objects bounding rect to viewport coordinates to correctly draw them onto pixmap
		pol=viewp.mapFromScene(ret);

		//Configure the viewport area to be copied
		retv.setTopLeft(pol.at(0));
		retv.setTopRight(pol.at(1));
		retv.setBottomRight(pol.at(2));
		retv.setBottomLeft(pol.at(3));

		//Creates the output pixmap
		pix=QPixmap(retv.size());
		pix.fill();
		QPainter p(&pix);

		//Setting optimizations on the painter
		p.setRenderHint(QPainter::Antialiasing, true);
		p.setRenderHint(QPainter::TextAntialiasing, true);
		p.setRenderHint(QPainter::SmoothPixmapTransform, true);

		emit s_progressUpdated(50, trUtf8("Rendering objects onto the output pixmap..."), BASE_OBJECT);

		//Render the entire viewport onto the pixmap
		viewp.render(&p, QRectF(QPointF(0,0), pix.size()), retv);

		//Restore the scene options
		ObjectsScene::setGridOptions(shw_grd, align_objs, shw_dlm);

		//Updates the scene to apply the restoration of grid and delimiter statuses
		scene->update();

		//If the pixmap is not saved raises an error
		if(!pix.save(filename))
			throw Exception(Exception::getErrorMessage(ERR_FILE_NOT_WRITTEN).arg(Utf8String::create(filename)),
											ERR_FILE_NOT_WRITTEN,__PRETTY_FUNCTION__,__FILE__,__LINE__);

		emit s_exportFinished();
	}
	catch(Exception &e)
	{
		throw Exception(e.getErrorMessage(), e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
	}
}
Example #7
0
void ModelExportHelper::exportToDBMS(DatabaseModel *db_model, Connection conn, const QString &pgsql_ver, bool ignore_dup, bool drop_db, bool simulate)
{
	int type_id;
	QString  version, sql_buf, sql_cmd, lin;
	Connection new_db_conn;
	unsigned i, count;
	ObjectType types[]={OBJ_ROLE, OBJ_TABLESPACE};
	BaseObject *object=nullptr;
	vector<Exception> errors;
	QTextStream ts;
	bool ddl_tk_found=false;

	/* Error codes treated in this method
			42P04 	duplicate_database
			42723 	duplicate_function
			42P06 	duplicate_schema
			42P07 	duplicate_table
			42710 	duplicate_object
			42701   duplicate_column
			42P16   invalid_table_definition

		 Reference:
			http://www.postgresql.org/docs/current/static/errcodes-appendix.html*/
	QString error_codes[]={"42P04", "42723", "42P06", "42P07", "42710", "42701", "42P16"};
	vector<QString> err_codes_vect(error_codes, error_codes + sizeof(error_codes) / sizeof(QString));

	try
	{
		if(!db_model)
			throw Exception(ERR_ASG_NOT_ALOC_OBJECT,__PRETTY_FUNCTION__,__FILE__,__LINE__);

		/* If the export is called using ignore duplications or drop database and simulation mode at same time
		an error is raised because the simulate mode (mainly used as SQL validation) cannot
		undo column addition (this can be changed in the future) */
		if(simulate && (ignore_dup || drop_db))
			throw Exception(ERR_MIX_INCOMP_EXPORT_OPTS,__PRETTY_FUNCTION__,__FILE__,__LINE__);

		connect(db_model, SIGNAL(s_objectLoaded(int,QString,uint)), this, SLOT(updateProgress(int,QString,uint)));

		export_canceled=false;
		db_created=false;
		progress=sql_gen_progress=0;
		created_objs[OBJ_ROLE]=created_objs[OBJ_TABLESPACE]=-1;
		conn.connect();

		//Retrive the DBMS version in order to generate the correct code
		version=(conn.getPgSQLVersion()).mid(0,3);

		//Overriding the DBMS version case the version is informed on parameter
		if(!pgsql_ver.isEmpty())
		{
			SchemaParser::setPgSQLVersion(pgsql_ver);
			emit s_progressUpdated(progress, trUtf8("PostgreSQL version detection overrided. Using version %1...").arg(pgsql_ver));
		}
		else
		{
			SchemaParser::setPgSQLVersion(version);
			emit s_progressUpdated(progress, trUtf8("PostgreSQL %1 server detected...").arg(version));
		}

		if(ignore_dup)
		{
			emit s_progressUpdated(progress, trUtf8("Ignoring object duplication errors..."));

			//Save the current status for ALTER command generation for table columns/constraints
			saveGenAtlerCmdsStatus(db_model);
		}

		if(drop_db)
		{
			emit s_progressUpdated(progress, trUtf8("Trying to drop database `%1'...").arg(db_model->getName()));
			conn.executeDDLCommand(QString("DROP DATABASE IF EXISTS %1;").arg(db_model->getName(true)));
		}

		if(simulate)
			emit s_progressUpdated(progress, trUtf8("Simulation mode activated..."));

		//Creates the roles and tablespaces separately from the other objects
		for(type_id=0; type_id < 2 && !export_canceled; type_id++)
		{
			count=db_model->getObjectCount(types[type_id]);

			for(i=0; i < count && !export_canceled; i++)
			{
				object=db_model->getObject(i, types[type_id]);
				progress=((10 * (type_id+1)) + ((i/static_cast<float>(count)) * 10));

				try
				{
					if(!object->isSQLDisabled())
					{
						//Emits a signal indicating that the object is being exported
						emit s_progressUpdated(progress,
																	 trUtf8("Creating object `%1' (%2)...").arg(Utf8String::create(object->getName())).arg(object->getTypeName()),
																	 object->getObjectType());

						sql_cmd=object->getCodeDefinition(SchemaParser::SQL_DEFINITION);
						conn.executeDDLCommand(sql_cmd);
					}
				}
				catch(Exception &e)
				{
					/* Raises an error if the object is duplicated and the ignore duplicity is not set or the error
					returned by the server is other than object duplicity */
					if(!ignore_dup ||
						 (ignore_dup &&
							std::find(err_codes_vect.begin(), err_codes_vect.end(), e.getExtraInfo())==err_codes_vect.end()))
						throw Exception(e.getErrorMessage(),
														e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e, sql_cmd);
					else
						//If the object is duplicated store the error on a vector
						errors.push_back(e);
				}

				created_objs[types[type_id]]++;
			}
		}

		try
		{
			if(!db_model->isSQLDisabled() && !export_canceled)
			{
				//Creating the database on the DBMS
				emit s_progressUpdated(progress,
															 trUtf8("Creating database `%1'...").arg(Utf8String::create(db_model->getName())),
															 OBJ_DATABASE);
				sql_cmd=db_model->__getCodeDefinition(SchemaParser::SQL_DEFINITION);
				conn.executeDDLCommand(sql_cmd);
				db_created=true;
			}
		}
		catch(Exception &e)
		{
			/* Raises an error if the object is duplicated and the ignore duplicity is not set or the error
			returned by the server is other than object duplicity */
			if(!ignore_dup ||
				 (ignore_dup &&
					std::find(err_codes_vect.begin(), err_codes_vect.end(), e.getExtraInfo())==err_codes_vect.end()))
				throw Exception(e.getErrorMessage(),
												e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e, sql_cmd);
			else
				errors.push_back(e);
		}

		if(!export_canceled)
		{
			//Connects to the new created database to create the other objects
			progress=20;
			new_db_conn=conn;
			new_db_conn.setConnectionParam(Connection::PARAM_DB_NAME, db_model->getName());
			emit s_progressUpdated(progress,
														 trUtf8("Connecting to database `%1'...").arg(Utf8String::create(db_model->getName())));

			new_db_conn.connect();
			progress=30;
			//Creating the other object types
			emit s_progressUpdated(progress, trUtf8("Creating objects on database `%1'...").arg(Utf8String::create(db_model->getName())));

			//Generates the sql from entire model
			sql_buf=db_model->getCodeDefinition(SchemaParser::SQL_DEFINITION, false);

			/* Extract each SQL command from the buffer and execute them separately. This is done
			 to permit the user, in case of error, identify what object is wrongly configured. */
			ts.setString(&sql_buf);
			unsigned aux_prog=0, curr_size=0, buf_size=sql_buf.size();

			progress+=(sql_gen_progress/progress);
			sql_cmd.clear();

			while(!ts.atEnd() && !export_canceled)
			{
				try
				{
					//Cleanup single line comments
					lin=ts.readLine();
					curr_size+=lin.size();
					aux_prog=progress + ((curr_size/static_cast<float>(buf_size)) * 70);

					ddl_tk_found=(lin.indexOf(ParsersAttributes::DDL_END_TOKEN) >= 0);
					lin.remove(QRegExp("^(--)+(.)+$"));

					//If the line isn't empty after cleanup it will be included on sql command
					if(!lin.isEmpty())
						sql_cmd += lin + "\n";

					//If the ddl end token is found
					if(ddl_tk_found || (!sql_cmd.isEmpty() && ts.atEnd()))
					{
						//Regexp used to extract the object being created
						QRegExp reg=QRegExp("(CREATE)(.)+(\n)", Qt::CaseSensitive);
												//sql_cmd = sql_cmd.simplified();

						//Check if the regex matches the sql command
						if(reg.exactMatch(sql_cmd))
						{
							QString obj_type, obj_name;
							QRegExp reg_aux;
							unsigned obj_id;
							ObjectType obj_types[]={ OBJ_FUNCTION, OBJ_TRIGGER, OBJ_INDEX,
																			 OBJ_RULE,	OBJ_TABLE, OBJ_VIEW, OBJ_DOMAIN,
																			 OBJ_SCHEMA,	OBJ_AGGREGATE, OBJ_OPFAMILY,
																			 OBJ_OPCLASS, OBJ_OPERATOR,  OBJ_SEQUENCE,
																			 OBJ_CONVERSION, OBJ_CAST,	OBJ_LANGUAGE,
																			 OBJ_COLLATION, OBJ_EXTENSION, OBJ_TYPE };
							unsigned count=sizeof(obj_types)/sizeof(ObjectType);
							int pos=0;

							//Get the fisrt line of the sql command, that contains the CREATE ... statement
							lin=sql_cmd.mid(0, sql_cmd.indexOf('\n'));

							for(obj_id=0; obj_id < count; obj_id++)
							{
								//Check if the keyword for the current object exists on string
								reg_aux.setPattern(QString("(CREATE)(.)*(%1)%2")
																	 .arg(BaseObject::getSQLName(obj_types[obj_id]))
																	 .arg(obj_types[obj_id]==OBJ_INDEX ? "( )*(CONCURRENTLY)?" : ""));
								pos=reg_aux.indexIn(lin);

								if(pos >= 0)
								{
									//Extracts from the line the string starting with the object's name
									lin=lin.mid(reg_aux.matchedLength(), sql_cmd.indexOf('\n')).simplified();

									//Stores the object type name
									obj_type=BaseObject::getTypeName(obj_types[obj_id]);

									if(obj_types[obj_id]!=OBJ_CAST)
									{
										//The object name is the first element when splitting the string with space separator
										obj_name=lin.split(' ').at(0);
										obj_name.remove('(');
									}
									else
									{
										obj_name="cast" + lin.replace(" AS ",",");
									}

									obj_name.remove(';');
									break;
								}
							}

							emit s_progressUpdated(aux_prog,
																		 trUtf8("Creating object `%1' (%2)...").arg(obj_name).arg(obj_type),
																		 obj_types[obj_id]);
						}
						else
							//General commands like alter / set aren't explicitly shown
							emit s_progressUpdated(aux_prog, trUtf8("Executing auxiliary command..."));

						//Executes the extracted SQL command
						if(!sql_cmd.isEmpty())
							new_db_conn.executeDDLCommand(sql_cmd);

						sql_cmd.clear();
						ddl_tk_found=false;
					}
				}
				catch(Exception &e)
				{
					if(ddl_tk_found) ddl_tk_found=false;

					if(!ignore_dup ||
						 (ignore_dup &&
							std::find(err_codes_vect.begin(), err_codes_vect.end(), e.getExtraInfo())==err_codes_vect.end()))
						throw Exception(Exception::getErrorMessage(ERR_EXPORT_FAILURE).arg(Utf8String::create(sql_cmd)),
														ERR_EXPORT_FAILURE,__PRETTY_FUNCTION__,__FILE__,__LINE__,&e, sql_cmd);
					else
					{
						sql_cmd.clear();
						errors.push_back(e);
						sleepThread(10);
					}
				}
			}
		}

		disconnect(db_model, nullptr, this, nullptr);

		if(ignore_dup)
			restoreGenAtlerCmdsStatus();

		//Closes the new opened connection
		if(new_db_conn.isStablished()) new_db_conn.close();

		/* If the process was a simulation or even canceled undo the export
		removing the created objects */
		if(simulate || export_canceled)
			undoDBMSExport(db_model, conn);

		if(conn.isStablished())
			conn.close();

		if(!export_canceled)
			emit s_exportFinished();
		else
			emit s_exportCanceled();

		sleepThread(20);
	}
	catch(Exception &e)
	{
		disconnect(db_model, nullptr, this, nullptr);

		if(ignore_dup)
			restoreGenAtlerCmdsStatus();

		try
		{
			//Closes the new opened connection
			if(new_db_conn.isStablished()) new_db_conn.close();

			//Undo the export removing the created objects
			undoDBMSExport(db_model, conn);
		}
		catch(Exception &){}

		if(conn.isStablished())	conn.close();

		/* When running in a separated thread (other than the main application thread)
		redirects the error in form of signal */
		if(this->thread() && this->thread()!=qApp->thread())
		{
			errors.push_back(e);
			emit s_exportAborted(Exception(e.getErrorMessage(), e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, errors));
		}
		else
		{
			//Redirects any error to the user
			if(errors.empty())
				throw Exception(e.getErrorMessage(),e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
			else
			{
				errors.push_back(e);
				throw Exception(e.getErrorMessage(),__PRETTY_FUNCTION__,__FILE__,__LINE__, errors);
			}
		}
	}
}
Example #8
0
void ModelsDiffHelper::processDiffInfos(void)
{
    BaseObject *object=nullptr;
    Relationship *rel=nullptr;
    map<unsigned, QString> drop_objs, create_objs, alter_objs, truncate_tabs;
    vector<BaseObject *> drop_vect, create_vect, drop_cols;
    unsigned diff_type, schema_id=0, idx=0;
    ObjectType obj_type;
    map<unsigned, QString>::reverse_iterator ritr, ritr_end;
    attribs_map attribs;
    QString alter_def, no_inherit_def, inherit_def, set_perms,
            unset_perms, fk_defs, col_drop_def;
    SchemaParser schparser;
    Type *type=nullptr;
    vector<Type *> types;
    Constraint *constr=nullptr;
    Column *col=nullptr, *aux_col=nullptr;
    Table *parent_tab=nullptr;
    bool skip_obj=false;
    QStringList sch_names;

    try
    {
        if(!diff_infos.empty())
            emit s_progressUpdated(0, trUtf8("Processing diff infos..."));

        //Reuniting the schema names to inject a SET search_path command
        for(auto &schema : *imported_model->getObjectList(OBJ_SCHEMA))
            sch_names.push_back(schema->getName(true));

        //Separating the base types
        for(ObjectsDiffInfo diff : diff_infos)
        {
            type=dynamic_cast<Type *>(diff.getObject());

            if(type && type->getConfiguration()==Type::BASE_TYPE)
            {
                type->convertFunctionParameters();
                types.push_back(type);
            }
        }

        for(ObjectsDiffInfo diff : diff_infos)
        {
            diff_type=diff.getDiffType();
            object=diff.getObject();
            obj_type=object->getObjectType();
            rel=dynamic_cast<Relationship *>(object);
            constr=dynamic_cast<Constraint *>(object);
            col=dynamic_cast<Column *>(object);

            emit s_progressUpdated((idx++/static_cast<float>(diff_infos.size())) * 100,
                                   trUtf8("Processing `%1' info for object `%2' (%3)...")
                                   .arg(diff.getDiffTypeString()).arg(object->getSignature()).arg(object->getTypeName()),
                                   obj_type);

            /* Preliminary verification for check constraints: there is the need to
               check if the constraint is added by generalization or if this is not the case
               if it already exists in a ancestor table of its parent, this avoid the generation
               of commands to create or drop an inherited constraint raising errors when export the diff */
            if(constr && constr->getConstraintType()==ConstraintType::check)
            {
                parent_tab=dynamic_cast<Table *>(constr->getParentTable());
                skip_obj=constr->isAddedByGeneralization();

                for(unsigned i=0; i < parent_tab->getAncestorTableCount() && !skip_obj; i++)
                    skip_obj=(parent_tab->getAncestorTable(i)->getConstraint(constr->getName())!=nullptr);

                if(skip_obj) continue;
            }
            //Igoring any operation done over inherited columns
            else if(col)
            {
                parent_tab=dynamic_cast<Table *>(col->getParentTable());
                skip_obj=col->isAddedByGeneralization();

                for(unsigned i=0; i < parent_tab->getAncestorTableCount() && !skip_obj; i++)
                {
                    aux_col=parent_tab->getAncestorTable(i)->getColumn(col->getName());
                    skip_obj=(aux_col && aux_col->getType().getAliasType()==col->getType());
                }

                if(skip_obj) continue;
            }

            //Generating the DROP commands
            if(diff_type==ObjectsDiffInfo::DROP_OBJECT)
            {
                if(rel)
                    //Undoing inheritances
                    no_inherit_def+=rel->getInheritDefinition(true);
                else if(obj_type==OBJ_PERMISSION)
                    //Unsetting permissions
                    unset_perms+=object->getDropDefinition(diff_opts[OPT_CASCADE_MODE]);
                else
                {
                    //Ordinary drop commands for any object except columns
                    if(obj_type!=OBJ_COLUMN)
                        drop_objs[object->getObjectId()]=getCodeDefinition(object, true);
                    else
                    {
                        /* Special case for columns: due to cases like inheritance there is the
                           the need to drop the columns in the normal order of creation to avoid
                           error like 'drop inherited column' or wrong propagation of drop on all
                           child tables. */
                        drop_cols.push_back(object);
                    }
                }
            }
            //Generating the CREATE commands
            else if(diff_type==ObjectsDiffInfo::CREATE_OBJECT)
            {
                if(rel)
                    //Creating inheritances
                    inherit_def+=rel->getInheritDefinition(false);
                else if(obj_type==OBJ_PERMISSION)
                    //Setting permissions
                    set_perms+=object->getCodeDefinition(SchemaParser::SQL_DEFINITION);
                else
                {
                    //Generating fks definitions in a separated variable in order to append them at create commands maps
                    if(object->getObjectType()==OBJ_CONSTRAINT &&
                            dynamic_cast<Constraint *>(object)->getConstraintType()==ConstraintType::foreign_key)
                        fk_defs+=getCodeDefinition(object, false);
                    else
                    {
                        create_objs[object->getObjectId()]=getCodeDefinition(object, false);

                        if(obj_type==OBJ_SCHEMA)
                            sch_names.push_back(object->getName(true));
                    }
                }
            }
            //Generating the ALTER commands
            else if(diff_type==ObjectsDiffInfo::ALTER_OBJECT)
            {
                //Recreating the object instead of generating an ALTER command for it
                if((diff_opts[OPT_FORCE_RECREATION] && obj_type!=OBJ_DATABASE) &&
                        (!diff_opts[OPT_RECREATE_UNCHANGEBLE] ||
                         (diff_opts[OPT_RECREATE_UNCHANGEBLE] && !object->acceptsAlterCommand())))
                {
                    recreateObject(object, drop_vect, create_vect);

                    //Generating the drop for the object's reference
                    for(auto &obj : drop_vect)
                        drop_objs[obj->getObjectId()]=getCodeDefinition(obj, true);

                    //Generating the create for the object's reference
                    for(auto &obj : create_vect)
                    {
                        //The there is no ALTER info registered for an object's reference
                        if(!isDiffInfoExists(ObjectsDiffInfo::ALTER_OBJECT, nullptr, obj, false))
                            create_objs[obj->getObjectId()]=getCodeDefinition(obj, false);
                    }

                    drop_vect.clear();
                    create_vect.clear();
                }
                else
                {
                    if(diff.getOldObject())
                        alter_def=diff.getOldObject()->getAlterDefinition(object);

                    if(!alter_def.isEmpty())
                    {
                        //Commenting out the ALTER DATABASE ... RENAME TO ... command if user chooses to preserve the original name
                        if(obj_type==OBJ_DATABASE && alter_def.contains("RENAME") && diff_opts[OPT_PRESERVE_DB_NAME])
                            alter_def.prepend(QString("-- "));

                        alter_objs[object->getObjectId()]=alter_def;

                        /* If the object is a column checks if the types of the columns are differents,
                           generating a TRUNCATE TABLE for the parent table */
                        if(obj_type==OBJ_COLUMN && diff_opts[OPT_TRUCANTE_TABLES])
                        {
                            Column *src_col=dynamic_cast<Column *>(object),
                                    *imp_col=dynamic_cast<Column *>(diff.getOldObject());
                            Table *tab=dynamic_cast<Table *>(src_col->getParentTable());

                            //If the truncate was not generated previously
                            if((*src_col->getType())!=(*imp_col->getType()) && truncate_tabs.count(tab->getObjectId())==0)
                                truncate_tabs[tab->getObjectId()]=tab->getTruncateDefinition(diff_opts[OPT_CASCADE_MODE]);
                        }
                    }
                }
            }
        }

        //Creating the shell types declaration right below on the DDL that creates their schemas
        for(Type *type : types)
        {
            schema_id=type->getSchema()->getObjectId();

            if(create_objs.count(schema_id)!=0)
                create_objs[schema_id]+=type->getCodeDefinition(SchemaParser::SQL_DEFINITION, true);
            else
                attribs[ParsersAttributes::CREATE_CMDS]+=type->getCodeDefinition(SchemaParser::SQL_DEFINITION, true);

            type->convertFunctionParameters(true);
        }

        //Generating the drop command for columns
        for(BaseObject *col : drop_cols)
            col_drop_def+=getCodeDefinition(col, true);

        diff_def.clear();

        if(!drop_objs.empty() || !create_objs.empty() || !alter_objs.empty() ||
                !inherit_def.isEmpty() || !no_inherit_def.isEmpty() || !set_perms.isEmpty() ||
                !fk_defs.isEmpty() || !col_drop_def.isEmpty())
        {
            sch_names.removeDuplicates();

            //Attributes used on the diff schema file
            attribs[ParsersAttributes::HAS_CHANGES]=ParsersAttributes::_TRUE_;
            attribs[ParsersAttributes::PGMODELER_VERSION]=GlobalAttributes::PGMODELER_VERSION;
            attribs[ParsersAttributes::CHANGE]=QString::number(alter_objs.size());
            attribs[ParsersAttributes::CREATE]=QString::number(create_objs.size());
            attribs[ParsersAttributes::DROP]=QString::number(drop_objs.size());
            attribs[ParsersAttributes::TRUNCATE]=QString::number(truncate_tabs.size());
            attribs[ParsersAttributes::SEARCH_PATH]=sch_names.join(',');
            attribs[ParsersAttributes::ALTER_CMDS]=QString();
            attribs[ParsersAttributes::DROP_CMDS]=QString();
            attribs[ParsersAttributes::CREATE_CMDS]=QString();
            attribs[ParsersAttributes::TRUNCATE_CMDS]=QString();
            attribs[ParsersAttributes::UNSET_PERMS]=unset_perms;
            attribs[ParsersAttributes::SET_PERMS]=set_perms;
            attribs[ParsersAttributes::FUNCTION]=(source_model->getObjectCount(OBJ_FUNCTION)!=0 ? ParsersAttributes::_TRUE_ : QString());

            ritr=drop_objs.rbegin();
            ritr_end=drop_objs.rend();

            attribs[ParsersAttributes::DROP_CMDS]+=no_inherit_def;

            while(ritr!=ritr_end)
            {
                attribs[ParsersAttributes::DROP_CMDS]+=ritr->second;
                ritr++;
            }

            attribs[ParsersAttributes::DROP_CMDS]+=col_drop_def;



            for(auto &itr : create_objs)
                attribs[ParsersAttributes::CREATE_CMDS]+=itr.second;

            attribs[ParsersAttributes::CREATE_CMDS]+=fk_defs;
            attribs[ParsersAttributes::CREATE_CMDS]+=inherit_def;

            for(auto &itr : truncate_tabs)
                attribs[ParsersAttributes::TRUNCATE_CMDS]+=itr.second;

            for(auto &itr : alter_objs)
                attribs[ParsersAttributes::ALTER_CMDS]+=itr.second;

            //Generating the whole diff buffer
            schparser.setPgSQLVersion(pgsql_version);
            diff_def=schparser.getCodeDefinition(GlobalAttributes::SCHEMAS_ROOT_DIR + GlobalAttributes::DIR_SEPARATOR +
                                                 GlobalAttributes::ALTER_SCHEMA_DIR + GlobalAttributes::DIR_SEPARATOR +
                                                 ParsersAttributes::DIFF + GlobalAttributes::SCHEMA_EXT, attribs);
        }

        emit s_progressUpdated(100, trUtf8("Comparison between model and database finished."));
    }
    catch(Exception &e)
    {
        for(Type *type : types)
            type->convertFunctionParameters(true);

        throw Exception(e.getErrorMessage(),e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e);
    }
}
Example #9
0
void ModelsDiffHelper::diffModels(unsigned diff_type)
{
    map<unsigned, BaseObject *> obj_order;
    BaseObject *object=nullptr, *aux_object=nullptr;
    ObjectType obj_type;
    QString obj_name;
    unsigned idx=0, factor=0, prog=0;
    DatabaseModel *aux_model=nullptr;
    bool objs_differs=false, xml_differs=false;

    if(diff_canceled)
        return;

    if(diff_type==ObjectsDiffInfo::DROP_OBJECT)
    {
        /* For DROP detection, we must gather the objects from the database in order to check
           if they exists on the model. The object drop order here is the inverse of the creation order
           on the database */
        obj_order=imported_model->getCreationOrder(SchemaParser::SQL_DEFINITION, true);
        aux_model=source_model;
        factor=25;
    }
    else if(diff_type==ObjectsDiffInfo::CREATE_OBJECT ||
            diff_type==ObjectsDiffInfo::ALTER_OBJECT)
    {
        /* For creation or modification of objects the order followed is the same
           as the creation order on the source model */
        obj_order=source_model->getCreationOrder(SchemaParser::SQL_DEFINITION, true);
        aux_model=imported_model;
        factor=50;
        prog=50;
    }

    for(auto &obj_itr : obj_order)
    {
        object=obj_itr.second;
        obj_type=object->getObjectType();
        idx++;

        /* If this checking the following objects are discarded:
           1) BASE_RELATIONSHIP objects
           2) Objects which SQL code is disabled or system objects
           3) Cluster objects such as roles and tablespaces (when the operatoin is DROP and keep_cluster_objs is true) */
        if(obj_type!=BASE_RELATIONSHIP &&
                !object->isSystemObject() && !object->isSQLDisabled() &&
                ((diff_type==ObjectsDiffInfo::DROP_OBJECT && (!diff_opts[OPT_KEEP_CLUSTER_OBJS] || (diff_opts[OPT_KEEP_CLUSTER_OBJS] && obj_type!=OBJ_ROLE && obj_type!=OBJ_TABLESPACE))) ||
                 (diff_type!=ObjectsDiffInfo::DROP_OBJECT)))
        {
            emit s_progressUpdated(prog + ((idx/static_cast<float>(obj_order.size())) * factor),
                                   trUtf8("Processing object `%1' (%2)...").arg(object->getSignature()).arg(object->getTypeName()),
                                   object->getObjectType());

            //Processing objects that are not database, table child object (they are processed further)
            if(obj_type!=OBJ_DATABASE && !TableObject::isTableObject(obj_type))// && obj_type!=BASE_RELATIONSHIP)
            {
                /* Processing permissions. If the operation is DROP and keep_obj_perms is true the
                   the permission is ignored */
                if(obj_type==OBJ_PERMISSION &&
                        ((diff_type!=ObjectsDiffInfo::DROP_OBJECT) || !diff_opts[OPT_KEEP_OBJ_PERMS]))
                    generateDiffInfo(diff_type, object);

                //Processing relationship (in this case only generalization ones are considered)
                else if(obj_type==OBJ_RELATIONSHIP)
                {
                    Relationship *rel=dynamic_cast<Relationship *>(object);

                    if(rel->getRelationshipType()==BaseRelationship::RELATIONSHIP_GEN)
                    {
                        Table *ref_tab=nullptr, *rec_tab=nullptr;

                        ref_tab=aux_model->getTable(rel->getReferenceTable()->getName(true));
                        rec_tab=aux_model->getTable(rel->getReceiverTable()->getName(true));

                        /* If the receiver table exists on the model generates a info for the relationship,
                           otherwise, the generalization will be created automatically when the table is
                           created (see table's code defintion) */
                        if(rec_tab && !aux_model->getRelationship(ref_tab, rec_tab))
                            generateDiffInfo(diff_type, rel);
                    }
                }
                else if(obj_type!=OBJ_PERMISSION)
                {
                    //Get the object from the database
                    obj_name=object->getSignature();
                    aux_object=aux_model->getObject(obj_name, obj_type);

                    //Special case for many-to-many relationships
                    if(obj_type==OBJ_TABLE && !aux_object)
                        aux_object=getRelNNTable(obj_name, aux_model);

                    if(diff_type!=ObjectsDiffInfo::DROP_OBJECT && aux_object)
                    {
                        /* Try to get a diff from the retrieve object and the current object,
                           comparing only basic attributes like schema, tablespace and owner
                           this is why the BaseObject::getAlterDefinition is called */
                        objs_differs=!aux_object->BaseObject::getAlterDefinition(object).isEmpty();

                        //If the objects does not differ, try to compare their XML definition
                        if(!objs_differs)
                            xml_differs=object->isCodeDiffersFrom(aux_object,
                        {   ParsersAttributes::PROTECTED,
                            ParsersAttributes::SQL_DISABLED,
                            ParsersAttributes::RECT_VISIBLE,
                            ParsersAttributes::FILL_COLOR
                        },
                        {   ParsersAttributes::ROLE,
                            ParsersAttributes::TABLESPACE,
                            ParsersAttributes::COLLATION,
                            ParsersAttributes::POSITION,
                            ParsersAttributes::APPENDED_SQL,
                            ParsersAttributes::PREPENDED_SQL
                        });

                        //If a difference was detected between the objects
                        if(objs_differs || xml_differs)
                        {
                            generateDiffInfo(ObjectsDiffInfo::ALTER_OBJECT, object, aux_object);

                            //If the object is a table, do additional comparision between their child objects
                            if((!diff_opts[OPT_FORCE_RECREATION] || diff_opts[OPT_RECREATE_UNCHANGEBLE]) && object->getObjectType()==OBJ_TABLE)
                            {
                                Table *tab=dynamic_cast<Table *>(object), *aux_tab=dynamic_cast<Table *>(aux_object);
                                diffTables(tab, aux_tab, ObjectsDiffInfo::DROP_OBJECT);
                                diffTables(tab, aux_tab, ObjectsDiffInfo::CREATE_OBJECT);
                            }

                            objs_differs=xml_differs=false;
                        }
                    }
                    else if(!aux_object)
                        generateDiffInfo(diff_type, object);
                }
            }
            //Comparison for constraints (fks), triggers, rules, indexes
            else if(TableObject::isTableObject(obj_type))
                diffTableObject(dynamic_cast<TableObject *>(object), diff_type);
            //Comparison between model db and the imported db
            else if(diff_type==ObjectsDiffInfo::CREATE_OBJECT)
            {
                if(!source_model->getAlterDefinition(imported_model).isEmpty())
                    generateDiffInfo(ObjectsDiffInfo::ALTER_OBJECT, source_model, imported_model);
            }

            if(diff_canceled)
                break;
        }
        else
        {
            generateDiffInfo(ObjectsDiffInfo::IGNORE_OBJECT, object);
            emit s_progressUpdated(prog + ((idx/static_cast<float>(obj_order.size())) * factor),
                                   trUtf8("Skipping object `%1' (%2)...").arg(object->getSignature()).arg(object->getTypeName()),
                                   object->getObjectType());

            if(diff_canceled)
                break;
        }
    }
}
void ModelValidationHelper::validateModel(void)
{
	if(!db_model)
		throw Exception(ERR_OPR_NOT_ALOC_OBJECT,__PRETTY_FUNCTION__,__FILE__,__LINE__);

	try
	{
		ObjectType types[]={ OBJ_ROLE, OBJ_TABLESPACE, OBJ_SCHEMA, OBJ_LANGUAGE, OBJ_FUNCTION,
												 OBJ_TYPE, OBJ_DOMAIN, OBJ_SEQUENCE, OBJ_OPERATOR, OBJ_OPFAMILY,
												 OBJ_OPCLASS, OBJ_COLLATION, OBJ_TABLE, OBJ_EXTENSION, OBJ_VIEW },
								aux_types[]={ OBJ_TABLE, OBJ_VIEW },
							 tab_obj_types[]={ OBJ_CONSTRAINT, OBJ_INDEX };
		unsigned i, i1, cnt, aux_cnt=sizeof(aux_types)/sizeof(ObjectType),
						count=sizeof(types)/sizeof(ObjectType), count1=sizeof(tab_obj_types)/sizeof(ObjectType);
		BaseObject *object=nullptr, *refer_obj=nullptr;
		vector<BaseObject *> refs, refs_aux, *obj_list=nullptr;
		vector<BaseObject *>::iterator itr;
		TableObject *tab_obj=nullptr;
		ValidationInfo info;
		Table *table=nullptr;
		Constraint *constr=nullptr;
		map<QString, vector<BaseObject *> > dup_objects;
		map<QString, vector<BaseObject *> >::iterator mitr;
		QString name, signal_msg="`%1' (%2)";

		warn_count=error_count=progress=0;
		val_infos.clear();
		valid_canceled=false;

		/* Step 1: Validating broken references. This situation happens when a object references another
		whose id is smaller than the id of the first one. */
		for(i=0; i < count && !valid_canceled; i++)
		{
			obj_list=db_model->getObjectList(types[i]);
			itr=obj_list->begin();

			while(itr!=obj_list->end()&& !valid_canceled)
			{
				object=(*itr);
				itr++;

				//Excluding the validation of system objects (created automatically)
				if(!object->isSystemObject())
				{
					emit s_objectProcessed(signal_msg.arg(object->getName()).arg(object->getTypeName()), object->getObjectType());

					db_model->getObjectReferences(object, refs);
					refs_aux.clear();

					while(!refs.empty() && !valid_canceled)
					{
						//Checking if the referrer object is a table object. In this case its parent table is considered
						tab_obj=dynamic_cast<TableObject *>(refs.back());
						constr=dynamic_cast<Constraint *>(tab_obj);

						/* If the current referrer object has an id less than reference object's id
						then it will be pushed into the list of invalid references. The only exception is
						for foreign keys that are discarded from any validation since they are always created
						at end of code defintion being free of any reference breaking. */
						if(object != refs.back() &&
							 (!constr || (constr && constr->getConstraintType()!=ConstraintType::foreign_key)) &&
							 ((!tab_obj && refs.back()->getObjectId() <= object->getObjectId()) ||
								(tab_obj && !tab_obj->isAddedByRelationship() &&
								 tab_obj->getParentTable()->getObjectId() <= object->getObjectId())))
						{
							if(tab_obj)
								refer_obj=tab_obj->getParentTable();
							else
								refer_obj=refs.back();

							//Push the referrer object only if not exists on the list
							if(std::find(refs_aux.begin(), refs_aux.end(), refer_obj)==refs_aux.end())
								refs_aux.push_back(refer_obj);
						}

						refs.pop_back();
					}

					//Case there is broken refereces to the object
					if(!refs_aux.empty())
					{
						//Configures a validation info
						info=ValidationInfo(ValidationInfo::BROKEN_REFERENCE, object, refs_aux);
						error_count++;

						val_infos.push_back(info);

						//Emit the signal containing the info
						emit s_validationInfoGenerated(info);
					}
				}
			}

			//Emit a signal containing the validation progress
			progress=((i+1)/static_cast<float>(count))*20;
			emit s_progressUpdated(progress, "");

			sleepThread(5);
		}


		/* Step 2: Validating name conflitcs between primary keys, unique keys, exclude constraints
		and indexs of all tables/views. The table and view names are checked too. */
		obj_list=db_model->getObjectList(OBJ_TABLE);
		itr=obj_list->begin();

		//Searching the model's tables and gathering all the constraints and index
		while(itr!=obj_list->end() && !valid_canceled)
		{
			table=dynamic_cast<Table *>(*itr);

			emit s_objectProcessed(signal_msg.arg(table->getName()).arg(object->getTypeName()), table->getObjectType());

			itr++;

			for(i=0; i < count1 && !valid_canceled; i++)
			{
				cnt=table->getObjectCount(tab_obj_types[i]);

				for(i1=0; i1 < cnt && !valid_canceled; i1++)
				{
					//Get the table object (constraint or index)
					tab_obj=dynamic_cast<TableObject *>(table->getObject(i1, tab_obj_types[i]));

					//Configures the full name of the object including the parent name
					name=tab_obj->getParentTable()->getSchema()->getName(true) + "." + tab_obj->getName(true);
					name.remove("\"");

					//Trying to convert the object to constraint
					constr=dynamic_cast<Constraint *>(tab_obj);

					/* If the object is an index or	a primary key, unique or exclude constraint,
					insert the object on duplicated	objects map */
					if((!constr ||
							(constr && (constr->getConstraintType()==ConstraintType::primary_key ||
													constr->getConstraintType()==ConstraintType::unique ||
													constr->getConstraintType()==ConstraintType::exclude))))
						dup_objects[name].push_back(tab_obj);
				}
			}

			sleepThread(5);
		}

		/* Inserting the tables and views to the map in order to check if there is table objects
			 that conflicts with thems */
		for(i=0; i < aux_cnt && !valid_canceled; i++)
		{
			obj_list=db_model->getObjectList(aux_types[i]);
			itr=obj_list->begin();
			while(itr!=obj_list->end() && !valid_canceled)
			{
				dup_objects[(*itr)->getName(true).remove("\"")].push_back(*itr);
				itr++;
			}

			sleepThread(5);
		}

		//Checking the map of duplicated objects
		mitr=dup_objects.begin();
		i=1;
		while(mitr!=dup_objects.end() && !valid_canceled)
		{
			/* If the vector of the current map element has more the one object
			indicates the duplicity thus generates a validation info */
			if(mitr->second.size() > 1)
			{
				refs.assign(mitr->second.begin() + 1, mitr->second.end());

				//Configures a validation info
				info=ValidationInfo(ValidationInfo::NO_UNIQUE_NAME, mitr->second.front(), refs);
				error_count++;
				refs.clear();

				val_infos.push_back(info);

				//Emit the signal containing the info
				emit s_validationInfoGenerated(info);
			}

			//Emit a signal containing the validation progress
			progress=20 + ((i/static_cast<float>(dup_objects.size()))*20);
			emit s_progressUpdated(progress, "");

			i++; mitr++;
			sleepThread(5);
		}

		if(!valid_canceled && !fix_mode)
		{
			//Step 3 (optional): Validating the SQL code onto a local DBMS.
			//Case the connection isn't specified indicates that the SQL validation will not be executed
			if(!conn)
			{
				//Emit a signal indicating the final progress
				emitValidationFinished();
			}
			//SQL validation only occurs when the model is completely validated.
			else
			{
				//If there is no errors start the dbms export thread
				if(error_count==0)
				{
					export_thread->start();
					emit s_sqlValidationStarted(true);
				}
				else
				{
					warn_count++;
					emitValidationFinished();
					emit s_validationInfoGenerated(ValidationInfo(trUtf8("There are pending errors! SQL validation will not be executed.")));
				}
			}
		}
	}
	catch(Exception &e)
	{
		throw Exception(e.getErrorMessage(), e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
	}
}
void ModelValidationHelper::redirectExportProgress(int prog, QString msg, ObjectType obj_type)
{
	progress=41 + (prog * 0.55);
	emit s_progressUpdated(progress, msg, obj_type);
}
void ModelExportHelper::exportToDBMS(DatabaseModel *db_model, DBConnection &conn, const QString &pgsql_ver, bool ignore_dup, bool simulate)
{
	int type_id;
	QString  version, sql_buf, sql_cmd, lin;
	DBConnection new_db_conn;
	unsigned i, count;
	ObjectType types[]={OBJ_ROLE, OBJ_TABLESPACE};
	BaseObject *object=nullptr;
	vector<Exception> errors;
	QTextStream ts;
	bool ddl_tk_found=false;

	/* Error codes treated in this method
			42P04 	duplicate_database
			42723 	duplicate_function
			42P06 	duplicate_schema
			42P07 	duplicate_table
			42710 	duplicate_object

		 Reference:
			http://www.postgresql.org/docs/current/static/errcodes-appendix.html*/
	QString error_codes[]={"42P04", "42723", "42P06", "42P07", "42710"};
	vector<QString> err_codes_vect(error_codes, error_codes + sizeof(error_codes) / sizeof(QString));

	if(!db_model)
		throw Exception(ERR_ASG_NOT_ALOC_OBJECT,__PRETTY_FUNCTION__,__FILE__,__LINE__);

	connect(db_model, SIGNAL(s_objectLoaded(int,QString,uint)), this, SLOT(updateProgress(int,QString,uint)));

	try
	{
		db_created=false;
		progress=sql_gen_progress=0;
		created_objs[OBJ_ROLE]=created_objs[OBJ_TABLESPACE]=-1;
		conn.connect();

		//Retrive the DBMS version in order to generate the correct code
		version=(conn.getDBMSVersion()).mid(0,3);

		//Overriding the DBMS version case the version is informed on parameter
		if(!pgsql_ver.isEmpty())
		{
			SchemaParser::setPgSQLVersion(pgsql_ver);
			emit s_progressUpdated(progress, trUtf8("PostgreSQL version detection overrided. Using version %1...").arg(pgsql_ver));
		}
		else
		{
			SchemaParser::setPgSQLVersion(version);
			emit s_progressUpdated(progress, trUtf8("PostgreSQL %1 server detected...").arg(version));
		}

		if(ignore_dup)
			emit s_progressUpdated(progress, trUtf8("Ignoring object duplication error..."));

		//Creates the roles and tablespaces separately from the other objects
		for(type_id=0; type_id < 2; type_id++)
		{
			count=db_model->getObjectCount(types[type_id]);

			for(i=0; i < count; i++)
			{
				object=db_model->getObject(i, types[type_id]);
				progress=((10 * (type_id+1)) + ((i/static_cast<float>(count)) * 10));

				//Emits a signal indicating that the object is being exported
				emit s_progressUpdated(progress,
															 trUtf8("Creating object `%1' (%2)...").arg(Utf8String::create(object->getName())).arg(object->getTypeName()));

				try
				{
					if(!object->isSQLDisabled())
					{
						sql_cmd=object->getCodeDefinition(SchemaParser::SQL_DEFINITION);
						conn.executeDDLCommand(sql_cmd);
					}
				}
				catch(Exception &e)
				{
					/* Raises an error if the object is duplicated and the ignore duplicity is not set or the error
					returned by the server is other than object duplicity */
					if(!ignore_dup ||
						 (ignore_dup &&
							std::find(err_codes_vect.begin(), err_codes_vect.end(), e.getExtraInfo())==err_codes_vect.end()))
						throw Exception(e.getErrorMessage(),
														e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e, sql_cmd);
					else
						//If the object is duplicated store the error on a vector
						errors.push_back(e);
				}

				created_objs[types[type_id]]++;
			}
		}

		try
		{
			if(!db_model->isSQLDisabled())
			{
				//Creating the database on the DBMS
				emit s_progressUpdated(progress, trUtf8("Creating database `%1'...").arg(Utf8String::create(db_model->getName())));
				sql_cmd=db_model->__getCodeDefinition(SchemaParser::SQL_DEFINITION);
				conn.executeDDLCommand(sql_cmd);
				db_created=true;
			}
		}
		catch(Exception &e)
		{
			/* Raises an error if the object is duplicated and the ignore duplicity is not set or the error
			returned by the server is other than object duplicity */
			if(!ignore_dup ||
				 (ignore_dup &&
					std::find(err_codes_vect.begin(), err_codes_vect.end(), e.getExtraInfo())==err_codes_vect.end()))
				throw Exception(e.getErrorMessage(),
												e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e, sql_cmd);
			else
				errors.push_back(e);
		}

		//Connects to the new created database to create the other objects
		progress=30;
		new_db_conn=conn;
		new_db_conn.setConnectionParam(DBConnection::PARAM_DB_NAME, db_model->getName());
		emit s_progressUpdated(progress, trUtf8("Connecting to database `%1'...").arg(Utf8String::create(db_model->getName())));

		new_db_conn.connect();
		progress=50;
		//Creating the other object types
		emit s_progressUpdated(progress, trUtf8("Creating objects on database `%1'...").arg(Utf8String::create(db_model->getName())));

		//Generates the sql from entire model
		sql_buf=db_model->getCodeDefinition(SchemaParser::SQL_DEFINITION, false);

		/* Extract each SQL command from the buffer and execute them separately. This is done
			 to permit the user, in case of error, identify what object is wrongly configured. */
		ts.setString(&sql_buf);
		i=1;
		progress+=(sql_gen_progress/progress);
		sql_cmd.clear();

		while(!ts.atEnd())
		{
			try
			{
				//Cleanup single line comments
				lin=ts.readLine();
				ddl_tk_found=(lin.indexOf(ParsersAttributes::DDL_END_TOKEN) >= 0);
				lin.remove(QRegExp("^(--)+(.)+$"));

				//If the line isn't empty after cleanup it will be included on sql command
				if(!lin.isEmpty())
					sql_cmd += lin + "\n";

				//If the ddl end token is found
				if(ddl_tk_found)
				{
					//Regexp used to extract the object being created
					QRegExp reg=QRegExp("(CREATE)(.)+(\n)", Qt::CaseSensitive);

					sql_cmd.simplified();

					//Check if the regex matches the sql command
					if(reg.exactMatch(sql_cmd))
					{
						QString obj_type, obj_name;
						ObjectType obj_types[]={ OBJ_FUNCTION, OBJ_TRIGGER, OBJ_INDEX,
																		 OBJ_RULE,	OBJ_TABLE, OBJ_VIEW, OBJ_DOMAIN,
																		 OBJ_SCHEMA,	OBJ_AGGREGATE, OBJ_OPFAMILY,
																		 OBJ_OPCLASS, OBJ_OPERATOR,  OBJ_SEQUENCE,
																		 OBJ_CONVERSION, OBJ_CAST,	OBJ_LANGUAGE,
																		 OBJ_COLLATION, OBJ_EXTENSION, OBJ_TYPE };
						unsigned count=sizeof(obj_types)/sizeof(ObjectType);
						int pos=0;

						for(unsigned i=0; i < count; i++)
						{
							//Check if the keyword for the current object exists on string
							pos=sql_cmd.indexOf(BaseObject::getSQLName(obj_types[i]));

							if(pos >= 0)
							{
								//Extracts from the line the string starting with the object's name
								lin=sql_cmd.mid(pos + BaseObject::getSQLName(obj_types[i]).size(),
																sql_cmd.indexOf('\n')).simplified();

								//Stores the object type name
								obj_type=BaseObject::getTypeName(obj_types[i]);

								//Special case of indexes, removes the "concurrently" keyword that cames after INDEX keyword
								if(obj_types[i]==OBJ_INDEX)
									lin.replace("CONCURRENTLY","");

								//The object name is the first element when splitting the string with space separator
								obj_name=lin.split(' ').at(0);
								obj_name.remove('(');
								obj_name.remove(';');
								break;
							}
						}

						emit s_progressUpdated(progress + (i/progress), trUtf8("Creating object `%1' (%2)...")
																	 .arg(obj_name)
																	 .arg(obj_type));
					}
					else
						//General commands like alter / set aren't explicitly shown
						emit s_progressUpdated(progress + (i/progress), trUtf8("Executing auxiliary command..."));

					//Executes the extracted SQL command
					if(!sql_cmd.isEmpty())
						new_db_conn.executeDDLCommand(sql_cmd);

					ddl_tk_found=false;
					sql_cmd.clear();
					i++;
				}
			}
			catch(Exception &e)
			{
				if(!ignore_dup ||
					 (ignore_dup &&
						std::find(err_codes_vect.begin(), err_codes_vect.end(), e.getExtraInfo())==err_codes_vect.end()))
					throw Exception(Exception::getErrorMessage(ERR_EXPORT_FAILURE).arg(Utf8String::create(sql_cmd)),
													ERR_EXPORT_FAILURE,__PRETTY_FUNCTION__,__FILE__,__LINE__,&e, sql_cmd);
				else
					errors.push_back(e);
			}
		}

		disconnect(db_model, nullptr, this, nullptr);

		//Closes the new opened connection
		if(new_db_conn.isStablished()) new_db_conn.close();

		/* If the process was a simulation undo the export
		removing the created objects */
		if(simulate)
			undoDBMSExport(db_model, conn);
	}
	catch(Exception &e)
	{
		disconnect(db_model, nullptr, this, nullptr);

		//Closes the new opened connection
		if(new_db_conn.isStablished()) new_db_conn.close();

		//Undo the export removing the created objects
		undoDBMSExport(db_model, conn);

		//Redirects any error to the user
		if(errors.empty())
			throw Exception(e.getErrorMessage(),e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
		else
		{
			errors.push_back(e);
			throw Exception(e.getErrorMessage(),__PRETTY_FUNCTION__,__FILE__,__LINE__, errors);
		}
	}
}