Skip to content

Commit c32914f

Browse files
author
jef
committedNov 22, 2007
attribute table: add attributes before applying attribute changes, fixes #763
please test git-svn-id: http://svn.osgeo.org/qgis/trunk@7642 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent d404b6e commit c32914f

File tree

3 files changed

+119
-97
lines changed

3 files changed

+119
-97
lines changed
 

‎src/app/qgsattributetable.cpp

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ void QgsAttributeTable::copySelectedRows()
408408

409409
bool QgsAttributeTable::commitChanges(QgsVectorLayer* layer)
410410
{
411-
bool isSuccessful = FALSE;
411+
bool isSuccessful = false;
412412

413413
if(layer)
414414
{
@@ -427,28 +427,42 @@ bool QgsAttributeTable::commitChanges(QgsVectorLayer* layer)
427427
deletedIds.insert(provider->indexFromFieldName(*it));
428428
}
429429

430-
QgsChangedAttributesMap attributeChanges; //convert mChangedValues to QgsChangedAttributesMap
431-
int fieldIndex;
430+
isSuccessful = true;
431+
if( !mAddedAttributes.empty() )
432+
{
433+
// add new attributes beforehand, so attribute changes can be applied
434+
isSuccessful = layer->commitAttributeChanges(QgsAttributeIds(), mAddedAttributes, QgsChangedAttributesMap());
435+
}
432436

433-
QMap<int, QMap<QString, QString> >::const_iterator att_it = mChangedValues.constBegin();
434-
for(; att_it != mChangedValues.constEnd(); ++att_it)
437+
if(isSuccessful)
435438
{
436-
QgsAttributeMap newAttMap;
437-
QMap<QString, QString>::const_iterator record_it = att_it->constBegin();
438-
for(; record_it != att_it->constEnd(); ++record_it)
439+
QgsChangedAttributesMap attributeChanges; //convert mChangedValues to QgsChangedAttributesMap
440+
int fieldIndex;
441+
442+
QMap<int, QMap<QString, QString> >::const_iterator att_it = mChangedValues.constBegin();
443+
for(; att_it != mChangedValues.constEnd(); ++att_it)
439444
{
440-
fieldIndex = provider->indexFromFieldName(record_it.key());
441-
if(fieldIndex != -1)
442-
{
443-
newAttMap.insert(fieldIndex, record_it.value());
444-
}
445-
}
446-
attributeChanges.insert(att_it.key(), newAttMap);
447-
}
448-
449-
isSuccessful = layer->commitAttributeChanges(deletedIds,
450-
mAddedAttributes,
451-
attributeChanges);
445+
QgsAttributeMap newAttMap;
446+
QMap<QString, QString>::const_iterator record_it = att_it->constBegin();
447+
for(; record_it != att_it->constEnd(); ++record_it)
448+
{
449+
fieldIndex = provider->indexFromFieldName(record_it.key());
450+
if(fieldIndex != -1)
451+
{
452+
newAttMap.insert(fieldIndex, record_it.value());
453+
}
454+
else
455+
{
456+
QgsDebugMsg("Changed attribute " + record_it.key() + " not found");
457+
}
458+
}
459+
attributeChanges.insert(att_it.key(), newAttMap);
460+
}
461+
462+
isSuccessful = layer->commitAttributeChanges(deletedIds,
463+
QgsNewAttributesMap(),
464+
attributeChanges);
465+
}
452466
}
453467
}
454468

‎src/providers/postgres/qgspostgresprovider.cpp

Lines changed: 81 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -144,82 +144,8 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
144144
calculateExtents();
145145
getFeatureCount();
146146

147-
// Get the relation oid for use in later queries
148-
sql = "SELECT oid FROM pg_class WHERE relname = '" + mTableName + "' AND relnamespace = ("
149-
"SELECT oid FROM pg_namespace WHERE nspname = '" + mSchemaName + "')";
150-
PGresult *tresult= PQexec(connection, (const char *)(sql.utf8()));
151-
QString tableoid = PQgetvalue(tresult, 0, 0);
152-
PQclear(tresult);
153-
154-
// Get the table description
155-
sql = "SELECT description FROM pg_description WHERE "
156-
"objoid = " + tableoid + " AND objsubid = 0";
157-
tresult = PQexec(connection, (const char*) sql.utf8());
158-
if (PQntuples(tresult) > 0)
159-
mDataComment = PQgetvalue(tresult, 0, 0);
160-
PQclear(tresult);
161-
162-
// Populate the field vector for this layer. The field vector contains
163-
// field name, type, length, and precision (if numeric)
164-
sql = "select * from " + mSchemaTableName + " limit 0";
165-
166-
PGresult *result = PQexec(connection, (const char *) (sql.utf8()));
167-
//--std::cout << "Field: Name, Type, Size, Modifier:" << std::endl;
168-
169-
// The queries inside this loop could possibly be combined into one
170-
// single query - this would make the code run faster.
171-
172-
for (int i=0; i < PQnfields(result); i++)
173-
{
174-
QString fieldName = PQfname(result, i);
175-
int fldtyp = PQftype(result, i);
176-
QString typOid = QString().setNum(fldtyp);
177-
int fieldModifier = PQfmod(result, i);
178-
QString fieldComment("");
179-
180-
sql = "SELECT typname, typlen FROM pg_type WHERE "
181-
"oid = (SELECT typelem FROM pg_type WHERE "
182-
"typelem = " + typOid + " AND typlen = -1)";
183-
184-
PGresult* oidResult = PQexec(connection, (const char *) sql);
185-
QString fieldTypeName = PQgetvalue(oidResult, 0, 0);
186-
QString fieldSize = PQgetvalue(oidResult, 0, 1);
187-
PQclear(oidResult);
188-
189-
sql = "SELECT attnum FROM pg_attribute WHERE "
190-
"attrelid = " + tableoid + " AND attname = '" + fieldName + "'";
191-
PGresult *tresult = PQexec(connection, (const char *)(sql.utf8()));
192-
QString attnum = PQgetvalue(tresult, 0, 0);
193-
PQclear(tresult);
194-
195-
sql = "SELECT description FROM pg_description WHERE "
196-
"objoid = " + tableoid + " AND objsubid = " + attnum;
197-
tresult = PQexec(connection, (const char*)(sql.utf8()));
198-
if (PQntuples(tresult) > 0)
199-
fieldComment = PQgetvalue(tresult, 0, 0);
200-
PQclear(tresult);
201-
202-
QgsDebugMsg("Field: " + attnum + " maps to " + QString::number( i ) + " " + fieldName + ", "
203-
+ fieldTypeName + " (" + QString::number(fldtyp) + "), " + fieldSize + ", " + QString::number(fieldModifier));
204-
205-
if(fieldName!=geometryColumn)
206-
{
207-
208-
QVariant::Type fieldType;
209-
if (fieldTypeName.find("int") != -1 || fieldTypeName.find("serial") != -1)
210-
fieldType = QVariant::Int;
211-
else if (fieldTypeName == "real" || fieldTypeName == "double precision" || \
212-
fieldTypeName.find("float") != -1)
213-
fieldType = QVariant::Double;
214-
else if (fieldTypeName != "bytea" )
215-
fieldType = QVariant::String;
216-
else
217-
continue;
218-
219-
attributeFields.insert(i, QgsField(fieldName, fieldType, fieldTypeName, fieldSize.toInt(), fieldModifier, fieldComment));
220-
}
221-
}
222-
PQclear(result);
147+
// load the field list
148+
loadFields();
223149

224150
// set the primary key
225151
getPrimaryKey();
@@ -778,6 +704,7 @@ void QgsPostgresProvider::reset()
778704
QString move = "move 0 in qgisf"; //move cursor to first record
779705
PQexec(connection, (const char *)(move.utf8()));
780706
mFeatureQueue.empty();
707+
loadFields();
781708
}
782709

783710
/** @todo XXX Perhaps this should be promoted to QgsDataProvider? */
@@ -796,6 +723,84 @@ QString QgsPostgresProvider::endianString()
796723
}
797724
}
798725

726+
void QgsPostgresProvider::loadFields()
727+
{
728+
QgsDebugMsg("Loading fields for table " + mTableName);
729+
730+
// Get the relation oid for use in later queries
731+
QString sql = "SELECT oid FROM pg_class WHERE relname = '" + mTableName + "' AND relnamespace = ("
732+
"SELECT oid FROM pg_namespace WHERE nspname = '" + mSchemaName + "')";
733+
PGresult *tresult= PQexec(connection, (const char *)(sql.utf8()));
734+
QString tableoid = PQgetvalue(tresult, 0, 0);
735+
PQclear(tresult);
736+
737+
// Get the table description
738+
sql = "SELECT description FROM pg_description WHERE "
739+
"objoid = " + tableoid + " AND objsubid = 0";
740+
tresult = PQexec(connection, (const char*) sql.utf8());
741+
if (PQntuples(tresult) > 0)
742+
mDataComment = PQgetvalue(tresult, 0, 0);
743+
PQclear(tresult);
744+
745+
// Populate the field vector for this layer. The field vector contains
746+
// field name, type, length, and precision (if numeric)
747+
sql = "select * from " + mSchemaTableName + " limit 0";
748+
749+
PGresult *result = PQexec(connection, (const char *) (sql.utf8()));
750+
//--std::cout << "Field: Name, Type, Size, Modifier:" << std::endl;
751+
752+
// The queries inside this loop could possibly be combined into one
753+
// single query - this would make the code run faster.
754+
755+
for (int i = 0; i < PQnfields(result); i++)
756+
{
757+
QString fieldName = PQfname(result, i);
758+
int fldtyp = PQftype(result, i);
759+
QString typOid = QString().setNum(fldtyp);
760+
int fieldModifier = PQfmod(result, i);
761+
QString fieldComment("");
762+
763+
sql = "SELECT typname, typlen FROM pg_type WHERE "
764+
"oid = (SELECT typelem FROM pg_type WHERE "
765+
"typelem = " + typOid + " AND typlen = -1)";
766+
767+
PGresult* oidResult = PQexec(connection, (const char *) sql);
768+
QString fieldTypeName = PQgetvalue(oidResult, 0, 0);
769+
QString fieldSize = PQgetvalue(oidResult, 0, 1);
770+
PQclear(oidResult);
771+
772+
sql = "SELECT attnum FROM pg_attribute WHERE "
773+
"attrelid = " + tableoid + " AND attname = '" + fieldName + "'";
774+
PGresult *tresult = PQexec(connection, (const char *)(sql.utf8()));
775+
QString attnum = PQgetvalue(tresult, 0, 0);
776+
PQclear(tresult);
777+
778+
sql = "SELECT description FROM pg_description WHERE "
779+
"objoid = " + tableoid + " AND objsubid = " + attnum;
780+
tresult = PQexec(connection, (const char*)(sql.utf8()));
781+
if (PQntuples(tresult) > 0)
782+
fieldComment = PQgetvalue(tresult, 0, 0);
783+
PQclear(tresult);
784+
785+
QgsDebugMsg("Field: " + attnum + " maps to " + QString::number(i) + " " + fieldName + ", "
786+
+ fieldTypeName + " (" + QString::number(fldtyp) + "), " + fieldSize + ", " + QString::number(fieldModifier));
787+
788+
if(fieldName!=geometryColumn)
789+
{
790+
QVariant::Type fieldType;
791+
if (fieldTypeName.find("int") != -1 || fieldTypeName.find("serial") != -1)
792+
fieldType = QVariant::Int;
793+
else if (fieldTypeName == "real" || fieldTypeName == "double precision" || \
794+
fieldTypeName.find("float") != -1)
795+
fieldType = QVariant::Double;
796+
else
797+
fieldType = QVariant::String;
798+
attributeFields.insert(i, QgsField(fieldName, fieldType, fieldTypeName, fieldSize.toInt(), fieldModifier, fieldComment));
799+
}
800+
}
801+
PQclear(result);
802+
}
803+
799804
QString QgsPostgresProvider::getPrimaryKey()
800805
{
801806
// check to see if there is an unique index on the relation, which

‎src/providers/postgres/qgspostgresprovider.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ class QgsPostgresProvider:public QgsVectorDataProvider
180180
QString dataComment() const;
181181

182182
/** Reset the layer - for a PostgreSQL layer, this means clearing the PQresult
183-
* pointer and setting it to 0
183+
* pointer, setting it to 0 and reloading the field list
184184
*/
185185
void reset();
186186

@@ -327,6 +327,9 @@ class QgsPostgresProvider:public QgsVectorDataProvider
327327
void repaintRequested();
328328

329329
private:
330+
/** Load the field list
331+
*/
332+
void loadFields();
330333

331334
bool mFirstFetch; //true if fetch forward is called the first time after select
332335
std::vector < QgsFeature > features;

0 commit comments

Comments
 (0)
Please sign in to comment.