1 /*
2 # PostgreSQL Database Modeler (pgModeler)
3 #
4 # Copyright 2006-2020 - Raphael Araújo e Silva <raphael@pgmodeler.io>
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation version 3.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # The complete text of GPLv3 is at LICENSE file on source code root directory.
16 # Also, you can get the complete GNU General Public License at <http://www.gnu.org/licenses/>
17 */
18 
19 #include "viewwidget.h"
20 #include "rulewidget.h"
21 #include "triggerwidget.h"
22 #include "indexwidget.h"
23 #include "baseform.h"
24 #include "referencewidget.h"
25 
ViewWidget(QWidget * parent)26 ViewWidget::ViewWidget(QWidget *parent): BaseObjectWidget(parent, ObjectType::View)
27 {
28 	try
29 	{
30 		ObjectsTableWidget *tab=nullptr;
31 		ObjectType types[]={ ObjectType::Trigger, ObjectType::Rule, ObjectType::Index };
32 		QGridLayout *grid=nullptr;
33 		QVBoxLayout *vbox=nullptr;
34 
35 		map<QString, vector<QWidget *> > fields_map;
36 		QFrame *frame=nullptr;
37 
38 		Ui_ViewWidget::setupUi(this);
39 
40 		code_txt=new NumberedTextEditor(this);
41 		code_txt->setReadOnly(true);
42 		code_hl=new SyntaxHighlighter(code_txt);
43 		code_hl->loadConfiguration(GlobalAttributes::getSQLHighlightConfPath());
44 		vbox=new QVBoxLayout(code_prev_tab);
45 		vbox->setContentsMargins(4,4,4,4);
46 		vbox->addWidget(code_txt);
47 
48 		cte_expression_txt=new NumberedTextEditor(this, true);
49 		cte_expression_hl=new SyntaxHighlighter(cte_expression_txt);
50 		cte_expression_hl->loadConfiguration(GlobalAttributes::getSQLHighlightConfPath());
51 		vbox=new QVBoxLayout(cte_tab);
52 		vbox->setContentsMargins(4,4,4,4);
53 		vbox->addWidget(cte_expression_txt);
54 
55 		tag_sel=new ObjectSelectorWidget(ObjectType::Tag, false, this);
56 		dynamic_cast<QGridLayout *>(options_gb->layout())->addWidget(tag_sel, 0, 1, 1, 4);
57 
58 		references_tab=new ObjectsTableWidget(ObjectsTableWidget::AllButtons ^ ObjectsTableWidget::UpdateButton, true, this);
59 		references_tab->setColumnCount(5);
60 		references_tab->setHeaderLabel(tr("Col./Expr."), 0);
61 		references_tab->setHeaderLabel(tr("Table alias"), 1);
62 		references_tab->setHeaderLabel(tr("Column alias"), 2);
63 		references_tab->setHeaderLabel(tr("Flags: SF FW AW EX VD"), 3);
64 		references_tab->setHeaderLabel(tr("Reference alias"), 4);
65 
66 		vbox=new QVBoxLayout(tabWidget->widget(0));
67 		vbox->setContentsMargins(4,4,4,4);
68 		vbox->addWidget(references_tab);
69 
70 		cte_expression_cp=new CodeCompletionWidget(cte_expression_txt, true);
71 
72 		//Configuring the table objects that stores the triggers and rules
73 		for(unsigned i=0, tab_id=1; i < sizeof(types)/sizeof(ObjectType); i++, tab_id++)
74 		{
75 			tab=new ObjectsTableWidget(ObjectsTableWidget::AllButtons ^
76 									  (ObjectsTableWidget::UpdateButton  | ObjectsTableWidget::MoveButtons), true, this);
77 
78 			objects_tab_map[types[i]]=tab;
79 
80 			grid=new QGridLayout;
81 			grid->addWidget(tab, 0,0,1,1);
82 			grid->setContentsMargins(4,4,4,4);
83 			tabWidget->widget(tab_id)->setLayout(grid);
84 
85 			connect(tab, SIGNAL(s_rowsRemoved()), this, SLOT(removeObjects()));
86 			connect(tab, SIGNAL(s_rowRemoved(int)), this, SLOT(removeObject(int)));
87 			connect(tab, SIGNAL(s_rowAdded(int)), this, SLOT(handleObject()));
88 			connect(tab, SIGNAL(s_rowEdited(int)), this, SLOT(handleObject()));
89 			connect(tab, SIGNAL(s_rowDuplicated(int,int)), this, SLOT(duplicateObject(int,int)));
90 		}
91 
92 		objects_tab_map[ObjectType::Trigger]->setColumnCount(6);
93 		objects_tab_map[ObjectType::Trigger]->setHeaderLabel(tr("Name"), 0);
94 		objects_tab_map[ObjectType::Trigger]->setHeaderIcon(QPixmap(PgModelerUiNs::getIconPath("uid")),0);
95 		objects_tab_map[ObjectType::Trigger]->setHeaderLabel(tr("Refer. Table"), 1);
96 		objects_tab_map[ObjectType::Trigger]->setHeaderIcon(QPixmap(PgModelerUiNs::getIconPath("table")),1);
97 		objects_tab_map[ObjectType::Trigger]->setHeaderLabel(tr("Firing"), 2);
98 		objects_tab_map[ObjectType::Trigger]->setHeaderIcon(QPixmap(PgModelerUiNs::getIconPath("trigger")),2);
99 		objects_tab_map[ObjectType::Trigger]->setHeaderLabel(tr("Events"), 3);
100 		objects_tab_map[ObjectType::Trigger]->setHeaderLabel(tr("Alias"), 4);
101 		objects_tab_map[ObjectType::Trigger]->setHeaderLabel(tr("Comment"), 5);
102 
103 		objects_tab_map[ObjectType::Index]->setColumnCount(4);
104 		objects_tab_map[ObjectType::Index]->setHeaderLabel(tr("Name"), 0);
105 		objects_tab_map[ObjectType::Index]->setHeaderIcon(QPixmap(PgModelerUiNs::getIconPath("uid")),0);
106 		objects_tab_map[ObjectType::Index]->setHeaderLabel(tr("Indexing"), 1);
107 		objects_tab_map[ObjectType::Index]->setHeaderLabel(tr("Alias"), 2);
108 		objects_tab_map[ObjectType::Index]->setHeaderLabel(tr("Comment"), 3);
109 
110 		objects_tab_map[ObjectType::Rule]->setColumnCount(5);
111 		objects_tab_map[ObjectType::Rule]->setHeaderLabel(tr("Name"), 0);
112 		objects_tab_map[ObjectType::Rule]->setHeaderIcon(QPixmap(PgModelerUiNs::getIconPath("uid")),0);
113 		objects_tab_map[ObjectType::Rule]->setHeaderLabel(tr("Execution"), 1);
114 		objects_tab_map[ObjectType::Rule]->setHeaderLabel(tr("Event"), 2);
115 		objects_tab_map[ObjectType::Rule]->setHeaderLabel(tr("Alias"), 3);
116 		objects_tab_map[ObjectType::Rule]->setHeaderLabel(tr("Comment"), 4);
117 
118 
119 		tablespace_sel->setEnabled(false);
120 		tablespace_lbl->setEnabled(false);
121 		configureFormLayout(view_grid, ObjectType::View);
122 
123 		fields_map[generateVersionsInterval(AfterVersion, PgSqlVersions::PgSqlVersion93)].push_back(recursive_rb);
124 		fields_map[generateVersionsInterval(AfterVersion, PgSqlVersions::PgSqlVersion93)].push_back(materialized_rb);
125 		fields_map[generateVersionsInterval(AfterVersion, PgSqlVersions::PgSqlVersion93)].push_back(with_no_data_chk);
126 		frame=generateVersionWarningFrame(fields_map);
127 		view_grid->addWidget(frame, view_grid->count()+1, 0, 1,3);
128 		frame->setParent(this);
129 
130 		connect(references_tab, SIGNAL(s_rowAdded(int)), this, SLOT(addReference(int)));
131 		connect(references_tab, SIGNAL(s_rowEdited(int)), this, SLOT(editReference(int)));
132 		connect(references_tab, SIGNAL(s_rowDuplicated(int,int)), this, SLOT(duplicateReference(int,int)));
133 		connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(updateCodePreview()));
134 
135 		connect(materialized_rb, SIGNAL(toggled(bool)), with_no_data_chk, SLOT(setEnabled(bool)));
136 		connect(materialized_rb, SIGNAL(toggled(bool)), tablespace_sel, SLOT(setEnabled(bool)));
137 		connect(materialized_rb, SIGNAL(toggled(bool)), tablespace_lbl, SLOT(setEnabled(bool)));
138 
139 		connect(materialized_rb, SIGNAL(toggled(bool)), this, SLOT(updateCodePreview()));
140 		connect(recursive_rb, SIGNAL(toggled(bool)),  this, SLOT(updateCodePreview()));
141 		connect(with_no_data_chk, SIGNAL(toggled(bool)), this, SLOT(updateCodePreview()));
142 		connect(tablespace_sel, SIGNAL(s_objectSelected()), this, SLOT(updateCodePreview()));
143 		connect(tablespace_sel, SIGNAL(s_selectorCleared()), this, SLOT(updateCodePreview()));
144 		connect(schema_sel, SIGNAL(s_objectSelected()), this, SLOT(updateCodePreview()));
145 		connect(schema_sel, SIGNAL(s_selectorCleared()), this, SLOT(updateCodePreview()));
146 
147 		configureTabOrder({ tag_sel, ordinary_rb, recursive_rb, with_no_data_chk, tabWidget });
148 		setMinimumSize(660, 650);
149 	}
150 	catch(Exception &e)
151 	{
152 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
153 	}
154 }
155 
getObjectTable(ObjectType obj_type)156 ObjectsTableWidget *ViewWidget::getObjectTable(ObjectType obj_type)
157 {
158 	if(objects_tab_map.count(obj_type) > 0)
159 		return objects_tab_map[obj_type];
160 
161 	return nullptr;
162 }
163 
164 template<class Class, class WidgetClass>
openEditingForm(TableObject * object)165 int ViewWidget::openEditingForm(TableObject *object)
166 {
167 	BaseForm editing_form(this);
168 	WidgetClass *object_wgt=new WidgetClass;
169 	object_wgt->setAttributes(this->model, this->op_list,
170 														dynamic_cast<BaseTable *>(this->object),
171 														dynamic_cast<Class *>(object));
172 	editing_form.setMainWidget(object_wgt);
173 
174 	return editing_form.exec();
175 }
176 
handleObject()177 void ViewWidget::handleObject()
178 {
179 	ObjectType obj_type=ObjectType::BaseObject;
180 	TableObject *object=nullptr;
181 	ObjectsTableWidget *obj_table=nullptr;
182 
183 	try
184 	{
185 		obj_type=getObjectType(sender());
186 		obj_table=getObjectTable(obj_type);
187 
188 		if(obj_table->getSelectedRow()>=0)
189 			object=reinterpret_cast<TableObject *>(obj_table->getRowData(obj_table->getSelectedRow()).value<void *>());
190 
191 		if(obj_type==ObjectType::Trigger)
192 			openEditingForm<Trigger,TriggerWidget>(object);
193 		else if(obj_type==ObjectType::Index)
194 			openEditingForm<Index,IndexWidget>(object);
195 		else
196 			openEditingForm<Rule,RuleWidget>(object);
197 
198 		listObjects(obj_type);
199 	}
200 	catch(Exception &e)
201 	{
202 		listObjects(obj_type);
203 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
204 	}
205 }
206 
duplicateObject(int curr_row,int new_row)207 void ViewWidget::duplicateObject(int curr_row, int new_row)
208 {
209 	ObjectType obj_type=ObjectType::BaseObject;
210 	BaseObject *object=nullptr, *dup_object=nullptr;
211 	ObjectsTableWidget *obj_table=nullptr;
212 	View *view = dynamic_cast<View *>(this->object);
213 	int op_id = -1;
214 
215 	try
216 	{
217 		obj_type=getObjectType(sender());
218 
219 		//Selects the object table based upon the passed object type
220 		obj_table=getObjectTable(obj_type);
221 
222 		//Gets the object reference if there is an item select on table
223 		if(curr_row >= 0)
224 			object = reinterpret_cast<BaseObject *>(obj_table->getRowData(curr_row).value<void *>());
225 
226 		PgModelerNs::copyObject(&dup_object, object, obj_type);
227 		dup_object->setName(PgModelerNs::generateUniqueName(dup_object, *view->getObjectList(obj_type), false, QString("_cp")));
228 
229 		op_id=op_list->registerObject(dup_object, Operation::ObjectCreated, new_row, this->object);
230 
231 		view->addObject(dup_object);
232 		view->setModified(true);
233 		listObjects(obj_type);
234 	}
235 	catch(Exception &e)
236 	{
237 		//If operation was registered
238 		if(op_id >= 0)
239 		{
240 			op_list->ignoreOperationChain(true);
241 			op_list->removeLastOperation();
242 			op_list->ignoreOperationChain(false);
243 		}
244 
245 		listObjects(obj_type);
246 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
247 	}
248 }
249 
removeObjects()250 void ViewWidget::removeObjects()
251 {
252 	View *view=nullptr;
253 	unsigned count, op_count=0, i;
254 	BaseObject *object=nullptr;
255 	ObjectType obj_type=getObjectType(sender());
256 
257 	try
258 	{
259 		view=dynamic_cast<View *>(this->object);
260 		op_count=op_list->getCurrentSize();
261 
262 		while(view->getObjectCount(obj_type) > 0)
263 		{
264 			object=view->getObject(0, obj_type);
265 			view->removeObject(object);
266 			op_list->registerObject(object, Operation::ObjectRemoved, 0, this->object);
267 		}
268 	}
269 	catch(Exception &e)
270 	{
271 		if(op_count < op_list->getCurrentSize())
272 		{
273 			count=op_list->getCurrentSize()-op_count;
274 			op_list->ignoreOperationChain(true);
275 
276 			for(i=0; i < count; i++)
277 			{
278 				op_list->undoOperation();
279 				op_list->removeLastOperation();
280 			}
281 
282 			op_list->ignoreOperationChain(false);
283 		}
284 
285 		listObjects(obj_type);
286 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
287 	}
288 }
289 
addReference(int row)290 void ViewWidget::addReference(int row)
291 {
292 	openReferenceForm(Reference(), row, false);
293 }
294 
duplicateReference(int orig_row,int new_row)295 void ViewWidget::duplicateReference(int orig_row, int new_row)
296 {
297  showReferenceData(references_tab->getRowData(orig_row).value<Reference>(),
298 									 getReferenceFlag(orig_row), new_row);
299 }
300 
removeObject(int row)301 void ViewWidget::removeObject(int row)
302 {
303 	View *view=nullptr;
304 	BaseObject *object=nullptr;
305 	ObjectType obj_type=getObjectType(sender());
306 
307 	try
308 	{
309 		view=dynamic_cast<View *>(this->object);
310 		object=view->getObject(row, obj_type);
311 		view->removeObject(object);
312 		op_list->registerObject(object, Operation::ObjectRemoved, row, this->object);
313 	}
314 	catch(Exception &e)
315 	{
316 		listObjects(obj_type);
317 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
318 	}
319 }
320 
getObjectType(QObject * sender)321 ObjectType ViewWidget::getObjectType(QObject *sender)
322 {
323 	ObjectType obj_type=ObjectType::BaseObject;
324 
325 	if(sender)
326 	{
327 		map<ObjectType, ObjectsTableWidget *>::iterator itr, itr_end;
328 
329 		itr=objects_tab_map.begin();
330 		itr_end=objects_tab_map.end();
331 
332 		while(itr!=itr_end && obj_type==ObjectType::BaseObject)
333 		{
334 			if(itr->second==sender)
335 				obj_type=itr->first;
336 
337 			itr++;
338 		}
339 	}
340 
341 	return obj_type;
342 }
343 
showObjectData(TableObject * object,int row)344 void ViewWidget::showObjectData(TableObject *object, int row)
345 {
346 	ObjectsTableWidget *tab=nullptr;
347 	Trigger *trigger=nullptr;
348 	Rule *rule=nullptr;
349 	Index *index=nullptr;
350 	ObjectType obj_type;
351 	QString str_aux;
352 	unsigned i;
353 	EventType events[]={ EventType::OnInsert, EventType::OnDelete,
354 						 EventType::OnTruncate,	EventType::OnUpdate };
355 
356 	obj_type=object->getObjectType();
357 	tab=objects_tab_map[obj_type];
358 
359 	//Column 0: Object name
360 	tab->setCellText(object->getName(),row,0);
361 
362 	if(obj_type==ObjectType::Trigger)
363 	{
364 		trigger=dynamic_cast<Trigger *>(object);
365 
366 		//Column 1: Table referenced by the trigger (constraint trigger)
367 		tab->clearCellText(row,1);
368 		if(trigger->getReferencedTable())
369 			tab->setCellText(trigger->getReferencedTable()->getName(true),row,1);
370 
371 		//Column 2: Trigger firing type
372 		tab->setCellText(~trigger->getFiringType(),row,2);
373 
374 		//Column 3: Events that fires the trigger
375 		for(i=0; i < sizeof(events)/sizeof(EventType); i++)
376 		{
377 			if(trigger->isExecuteOnEvent(events[i]))
378 				str_aux+=~events[i] + QString(", ");
379 		}
380 
381 		str_aux.remove(str_aux.size()-2, 2);
382 		tab->setCellText(str_aux ,row,3);
383 		tab->setCellText(trigger->getAlias(), row, 4);
384 	}
385 	else if(obj_type==ObjectType::Rule)
386 	{
387 		rule=dynamic_cast<Rule *>(object);
388 
389 		//Column 1: Rule execution type
390 		tab->setCellText(~rule->getExecutionType(),row,1);
391 
392 		//Column 2: Rule event type
393 		tab->setCellText(~rule->getEventType(),row,2);
394 
395 		tab->setCellText(rule->getAlias(), row, 3);
396 	}
397 	else
398 	{
399 		index=dynamic_cast<Index *>(object);
400 
401 		//Column 1: Indexing type
402 		tab->setCellText(~index->getIndexingType(),row,1);
403 		tab->setCellText(index->getAlias(), row, 2);
404 	}
405 
406 	tab->setCellText(object->getComment(), row, tab->getColumnCount() - 1);
407 	tab->setRowData(QVariant::fromValue<void *>(object), row);
408 }
409 
listObjects(ObjectType obj_type)410 void ViewWidget::listObjects(ObjectType obj_type)
411 {
412 	ObjectsTableWidget *tab=nullptr;
413 	unsigned count, i;
414 	View *view=nullptr;
415 
416 	try
417 	{
418 		//Gets the object table related to the object type
419 		tab=objects_tab_map[obj_type];
420 		view=dynamic_cast<View *>(this->object);
421 
422 		tab->blockSignals(true);
423 		tab->removeRows();
424 
425 		count=view->getObjectCount(obj_type);
426 		for(i=0; i < count; i++)
427 		{
428 			tab->addRow();
429 			showObjectData(dynamic_cast<TableObject*>(view->getObject(i, obj_type)), i);
430 		}
431 		tab->clearSelection();
432 		tab->blockSignals(false);
433 	}
434 	catch(Exception &e)
435 	{
436 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
437 	}
438 }
439 
openReferenceForm(Reference ref,int row,bool update)440 int ViewWidget::openReferenceForm(Reference ref, int row, bool update)
441 {
442 	BaseForm editing_form(this);
443 	ReferenceWidget *ref_wgt=new ReferenceWidget;
444 	int result = 0;
445 
446 	editing_form.setMainWidget(ref_wgt);
447 	editing_form.setButtonConfiguration(Messagebox::OkCancelButtons);
448 
449 	disconnect(editing_form.apply_ok_btn, SIGNAL(clicked(bool)), &editing_form, SLOT(accept()));
450 	connect(editing_form.apply_ok_btn, SIGNAL(clicked(bool)), ref_wgt, SLOT(applyConfiguration()));
451 	connect(ref_wgt, SIGNAL(s_closeRequested()), &editing_form, SLOT(accept()));
452 
453 	ref_wgt->setAttributes(ref, getReferenceFlag(row), model);
454 	result = editing_form.exec();
455 	disconnect(ref_wgt, nullptr, &editing_form, nullptr);
456 
457 	if(result == QDialog::Accepted)
458 		showReferenceData(ref_wgt->getReference(), ref_wgt->getReferenceFlags(), row);
459 	else if(!update)
460 		references_tab->removeRow(row);
461 
462 	return result;
463 }
464 
getReferenceFlag(int row)465 unsigned ViewWidget::getReferenceFlag(int row)
466 {
467 	QString flags_str = references_tab->getCellText(row, 3);
468 	unsigned ref_flags = 0;
469 
470 	if(flags_str.isEmpty())
471 		return 0;
472 
473 	if(flags_str[4] == '1')
474 		ref_flags = Reference::SqlViewDefinition;
475 	else
476 	{
477 		if(flags_str[0] == '1')
478 			ref_flags |= Reference::SqlReferSelect;
479 
480 		if(flags_str[1] == '1')
481 			ref_flags |= Reference::SqlReferFrom;
482 
483 		if(flags_str[2] == '1')
484 			ref_flags |= Reference::SqlReferWhere;
485 
486 		if(flags_str[3] == '1')
487 			ref_flags |= Reference::SqlReferEndExpr;
488 	}
489 
490 	return ref_flags;
491 }
492 
editReference(int ref_idx)493 void ViewWidget::editReference(int ref_idx)
494 {
495 	openReferenceForm(references_tab->getRowData(ref_idx).value<Reference>(), ref_idx, true);
496 }
497 
showReferenceData(Reference refer,unsigned ref_flags,unsigned row)498 void ViewWidget::showReferenceData(Reference refer, unsigned ref_flags, unsigned row)
499 {
500 	PhysicalTable *tab=nullptr;
501 	Column *col=nullptr;
502 	QString str_aux;
503 	bool	selec_from = (ref_flags & Reference::SqlReferSelect) == Reference::SqlReferSelect,
504 				from_where = (ref_flags & Reference::SqlReferFrom) == Reference::SqlReferFrom,
505 				after_where = (ref_flags & Reference::SqlReferWhere) == Reference::SqlReferWhere,
506 				end_expr = (ref_flags & Reference::SqlReferEndExpr) == Reference::SqlReferEndExpr,
507 				view_def = (ref_flags & Reference::SqlViewDefinition) == Reference::SqlViewDefinition;
508 
509 	if(refer.getReferenceType()==Reference::ReferColumn)
510 	{
511 		tab=refer.getTable();
512 		col=refer.getColumn();
513 
514 		/* If the table is allocated but not the column indicates that the reference
515 		 is to all table columns this way shows a string in format: [SCHEMA].[TABLE].* */
516 		if(tab && !col)
517 			references_tab->setCellText(tab->getName(true) + QString(".*"),row,0);
518 		/* If the table and column are allocated indicates that the reference
519 		 is to a specific column this way shows a string in format: [SCHEMA].[TABLE].[COLUMN] */
520 		else
521 			references_tab->setCellText(tab->getName(true) + QString(".") + col->getName(true),row,0);
522 
523 		references_tab->setCellText(refer.getAlias(),row,1);
524 
525 		if(col)
526 			references_tab->setCellText(refer.getColumnAlias(),row,2);
527 	}
528 	else
529 	{
530 		references_tab->setCellText(refer.getExpression().simplified(),row,0);
531 		references_tab->setCellText(refer.getAlias(),row,1);
532 	}
533 
534 	//Configures the string that denotes the SQL application for the reference
535 	str_aux+=(selec_from ? QString("1") : QString("0"));
536 	str_aux+=(from_where ? QString("1") : QString("0"));
537 	str_aux+=(after_where ? QString("1") : QString("0"));
538 	str_aux+=(end_expr ? QString("1") : QString("0"));
539 	str_aux+=(view_def ? QString("1") : QString("0"));
540 	references_tab->setCellText(str_aux, row, 3);
541 
542 	references_tab->setCellText(refer.getReferenceAlias(), row, 4);
543 
544 	refer.setDefinitionExpression(view_def);
545 	references_tab->setRowData(QVariant::fromValue<Reference>(refer), row);
546 }
547 
updateCodePreview()548 void ViewWidget::updateCodePreview()
549 {
550 	try
551 	{
552 		if(tabWidget->currentIndex()==tabWidget->count()-1)
553 		{
554 			View aux_view;
555 			Reference refer;
556 			QString str_aux;
557 			TableObject *tab_obj=nullptr;
558 			map<ObjectType, ObjectsTableWidget *>::iterator itr, itr_end;
559 			unsigned i, count, i1, expr_type[]={
560 												Reference::SqlReferSelect,
561 												Reference::SqlReferFrom,
562 												Reference::SqlReferWhere,
563 												Reference::SqlReferEndExpr,
564 												Reference::SqlViewDefinition};
565 
566 			aux_view.BaseObject::setName(name_edt->text().toUtf8());
567 			aux_view.BaseObject::setSchema(schema_sel->getSelectedObject());
568 			aux_view.setTablespace(tablespace_sel->getSelectedObject());
569 
570 			aux_view.setCommomTableExpression(cte_expression_txt->toPlainText().toUtf8());
571 			aux_view.setMaterialized(materialized_rb->isChecked());
572 			aux_view.setRecursive(recursive_rb->isChecked());
573 			aux_view.setWithNoData(with_no_data_chk->isChecked());
574 
575 			count=references_tab->getRowCount();
576 			for(i=0; i < count; i++)
577 			{
578 				refer=references_tab->getRowData(i).value<Reference>();
579 
580 				//Get the SQL application string for the current reference
581 				str_aux=references_tab->getCellText(i,3);
582 
583 				for(i1=0; i1 < sizeof(expr_type)/sizeof(unsigned); i1++)
584 				{
585 					if(str_aux[i1]=='1')
586 						aux_view.addReference(refer, expr_type[i1]);
587 				}
588 			}
589 
590 			itr=objects_tab_map.begin();
591 			itr_end=objects_tab_map.end();
592 
593 			//Inserts the triggers / rules into the auxiliary view
594 			while(itr!=itr_end)
595 			{
596 				count=itr->second->getRowCount();
597 
598 				//Make a copy of each view objects (rule/trigger) to the auxiliary view
599 				for(i=0; i < count; i++)
600 				{
601 					if(itr->first==ObjectType::Trigger)
602 					{
603 						tab_obj=new Trigger;
604 						(*dynamic_cast<Trigger *>(tab_obj))=
605 								(*reinterpret_cast<Trigger *>(itr->second->getRowData(i).value<void *>()));
606 					}
607 					else
608 					{
609 						tab_obj=new Rule;
610 						(*dynamic_cast<Rule *>(tab_obj))=
611 								(*reinterpret_cast<Rule *>(itr->second->getRowData(i).value<void *>()));
612 					}
613 					aux_view.addObject(tab_obj);
614 				}
615 
616 				itr++;
617 			}
618 			code_txt->setPlainText(aux_view.getCodeDefinition(SchemaParser::SqlDefinition));
619 		}
620 	}
621 	catch(Exception &e)
622 	{
623 		QString str_aux;
624 		//In case of error no code is outputed, showing a error message in the code preview widget
625 		str_aux=tr("/* Could not generate the SQL code. Make sure all attributes are correctly filled! ");
626 		str_aux+=QString("\n\n>> Returned error(s): \n\n%1*/").arg(e.getExceptionsText());
627 		code_txt->setPlainText(str_aux);
628 	}
629 }
630 
setAttributes(DatabaseModel * model,OperationList * op_list,Schema * schema,View * view,double px,double py)631 void ViewWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Schema *schema, View *view, double px, double py)
632 {
633 	unsigned i, count, ref_flags = 0;
634 	Reference refer;
635 
636 	if(!view)
637 	{
638 		view=new View;
639 
640 		if(schema)
641 			view->setSchema(schema);
642 
643 		/* Sets the 'new_object' flag as true indicating that the alocated table must be treated
644 			 as a recently created object */
645 		this->new_object=true;
646 	}
647 
648 	BaseObjectWidget::setAttributes(model,op_list, view, schema, px, py);
649 
650 	materialized_rb->setChecked(view->isMaterialized());
651 	recursive_rb->setChecked(view->isRecursive());
652 	with_no_data_chk->setChecked(view->isWithNoData());
653 
654 	cte_expression_cp->configureCompletion(model, cte_expression_hl);
655 
656 	op_list->startOperationChain();
657 	operation_count=op_list->getCurrentSize();
658 
659 	tag_sel->setModel(this->model);
660 	tag_sel->setSelectedObject(view->getTag());
661 
662 	cte_expression_txt->setPlainText(view->getCommomTableExpression());
663 
664 	count=view->getReferenceCount();
665 	references_tab->blockSignals(true);
666 
667 	for(i=0; i < count; i++)
668 	{
669 		references_tab->addRow();
670 
671 		ref_flags = 0;
672 		refer=view->getReference(i);
673 
674 		if(view->getReferenceIndex(refer, Reference::SqlViewDefinition) >= 0)
675 			ref_flags = Reference::SqlViewDefinition;
676 
677 		if(view->getReferenceIndex(refer, Reference::SqlReferSelect) >= 0)
678 			ref_flags |= Reference::SqlReferSelect;
679 
680 		if(view->getReferenceIndex(refer, Reference::SqlReferFrom) >= 0)
681 			ref_flags |= Reference::SqlReferFrom;
682 
683 		if(view->getReferenceIndex(refer, Reference::SqlReferWhere) >= 0)
684 			ref_flags |= Reference::SqlReferWhere;
685 
686 		if(view->getReferenceIndex(refer, Reference::SqlReferEndExpr) >= 0)
687 			ref_flags |= Reference::SqlReferEndExpr;
688 
689 		showReferenceData(refer, ref_flags, i);
690 	}
691 
692 	references_tab->blockSignals(false);
693 	references_tab->clearSelection();
694 
695 	listObjects(ObjectType::Trigger);
696 	listObjects(ObjectType::Rule);
697 	listObjects(ObjectType::Index);
698 }
699 
applyConfiguration()700 void ViewWidget::applyConfiguration()
701 {
702 	try
703 	{
704 		View *view=nullptr;
705 		ObjectType types[]={ ObjectType::Trigger, ObjectType::Rule, ObjectType::Index };
706 		unsigned expr_type[]={ Reference::SqlReferSelect,
707 													 Reference::SqlReferFrom,
708 													 Reference::SqlReferWhere,
709 													 Reference::SqlReferEndExpr,
710 													 Reference::SqlViewDefinition};
711 		Reference refer;
712 		QString str_aux;
713 
714 		if(!this->new_object)
715 			op_list->registerObject(this->object, Operation::ObjectModified);
716 		else
717 			registerNewObject();
718 
719 		BaseObjectWidget::applyConfiguration();
720 
721 		view=dynamic_cast<View *>(this->object);
722 		view->removeObjects();
723 		view->removeReferences();
724 		view->setMaterialized(materialized_rb->isChecked());
725 		view->setRecursive(recursive_rb->isChecked());
726 		view->setWithNoData(with_no_data_chk->isChecked());
727 		view->setCommomTableExpression(cte_expression_txt->toPlainText().toUtf8());
728 		view->setTag(dynamic_cast<Tag *>(tag_sel->getSelectedObject()));
729 
730 		for(unsigned i=0; i < references_tab->getRowCount(); i++)
731 		{
732 			refer=references_tab->getRowData(i).value<Reference>();
733 
734 			//Get the SQL application string for the current reference
735 			str_aux=references_tab->getCellText(i, 3);
736 			for(unsigned i=0; i < sizeof(expr_type)/sizeof(unsigned); i++)
737 			{
738 				if(str_aux[i]=='1')
739 					view->addReference(refer, expr_type[i]);
740 			}
741 		}
742 
743 		//Adds the auxiliary view objects into configured view
744 		for(unsigned type_id=0; type_id < sizeof(types)/sizeof(ObjectType); type_id++)
745 		{
746 			for(unsigned i=0; i < objects_tab_map[types[type_id]]->getRowCount(); i++)
747 				view->addObject(reinterpret_cast<TableObject *>(objects_tab_map[types[type_id]]->getRowData(i).value<void *>()));
748 		}
749 
750 		op_list->finishOperationChain();
751 		this->model->updateViewRelationships(view);
752 		finishConfiguration();
753 	}
754 	catch(Exception &e)
755 	{
756 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
757 	}
758 }
759 
cancelConfiguration()760 void ViewWidget::cancelConfiguration()
761 {
762 	BaseObjectWidget::cancelChainedOperation();
763 }
764