コード例 #1
0
//==================================================================================
//Return the value for a given column for the current record - Private const version
QVariant pqxxSqlCursor::pValue(uint pos)const
{	
	if (m_res->size() <= 0)
	{
		KexiDBDrvWarn << "pqxxSqlCursor::value - ERROR: result size not greater than 0" << endl;
		return QVariant();
	}

	if (pos>=(m_fieldCount+(m_containsROWIDInfo ? 1 : 0)))
	{
//		KexiDBDrvWarn << "pqxxSqlCursor::value - ERROR: requested position is greater than the number of fields" << endl;
		return QVariant();
	}

	KexiDB::Field *f = (m_fieldsExpanded && pos<QMIN(m_fieldsExpanded->count(), m_fieldCount)) 
		? m_fieldsExpanded->at(pos)->field : 0;

//	KexiDBDrvDbg << "pqxxSqlCursor::value(" << pos << ")" << endl;

	//from most to least frequently used types:
	if (f) //We probably have a schema type query so can use kexi to determin the row type
	{
		if ((f->isIntegerType()) || (/*ROWID*/!f && m_containsROWIDInfo && pos==m_fieldCount))
		{
			return (*m_res)[at()][pos].as(int());
		}
		else if (f->isTextType())
		{
			return QString::fromUtf8((*m_res)[at()][pos].c_str()); //utf8?
		}
		else if (f->isFPNumericType())
		{
			return (*m_res)[at()][pos].as(double());
		}
		else if (f->typeGroup() == Field::BLOBGroup)
		{
//			pqxx::result::field r = (*m_res)[at()][pos];
//			kdDebug() << r.name() << ", " << r.c_str() << ", " << r.type() << ", " << r.size() << endl;
			return ::pgsqlByteaToByteArray((*m_res)[at()][pos]);
		}
	}
	else // We probably have a raw type query so use pqxx to determin the column type
	{
		return pgsqlCStrToVariant((*m_res)[at()][pos]);
	}

	return QString::fromUtf8((*m_res)[at()][pos].c_str(), (*m_res)[at()][pos].size()); //utf8?
}
コード例 #2
0
ファイル: mdbmigrate.cpp プロジェクト: JeremiasE/KFormula
/* ************************************************************************** */
bool MDBMigrate::drv_readTableSchema(const QString& originalName,
                                     KexiDB::TableSchema& tableSchema)
{
    // Get the column meta-data
    MdbTableDef *tableDef = getTableDef(originalName);
    if (!tableDef) {
        kDebug() << "MDBMigrate::drv_getTableDef: couldn't find table "
        << originalName;
        return false;
    }
    mdb_read_columns(tableDef);
    kDebug() << "MDBMigrate::drv_readTableSchema: #cols = "
    << tableDef->num_cols;

    /*! Convert column data to Kexi TableSchema
        Nice mix of terminology here, MDBTools has columns, Kexi has fields. */
    MdbColumn *col;
    for (unsigned int i = 0; i < tableDef->num_cols; i++) {
        col = (MdbColumn*) g_ptr_array_index(tableDef->columns, i);

        // Field name
        QString fldName = QString::fromUtf8(col->name);
        kDebug() << "MDBMigrate::drv_readTableSchema: got column "
        << fldName << "\"" << col->name;

        QString fldID(KexiUtils::string2Identifier(fldName));

        // Field type
        KexiDB::Field *fld =
            new KexiDB::Field(fldID, type(col->col_type));

        kDebug() << "MDBMigrate::drv_readTableSchema: size "
        << col->col_size << " type " << type(col->col_type);
        fld->setCaption(fldName);
        tableSchema.addField(fld);
    }

    getPrimaryKey(&tableSchema, tableDef);

    // Free the column meta-data - as soon as it doesn't seg fault.
    //mdb_free_tabledef(tableDef);

    return true;
}
コード例 #3
0
/*! Get the types and properties for each column. */
bool MySQLMigrate::drv_readTableSchema(
	const QString& originalName, KexiDB::TableSchema& tableSchema)
{
//	m_table = new KexiDB::TableSchema(table);

//	//TODO IDEA: ask for user input for captions
//	tableSchema.setCaption(table + " table");

	//Perform a query on the table to get some data
	QString query = QString("SELECT * FROM `") + drv_escapeIdentifier(originalName) + "` LIMIT 0";
	if(d->executeSQL(query)) {
		MYSQL_RES *res = mysql_store_result(d->mysql);
		if (res != NULL) {
		
			unsigned int numFlds = mysql_num_fields(res);
			MYSQL_FIELD *fields = mysql_fetch_fields(res); 
			
			for(unsigned int i = 0; i < numFlds; i++) {
				QString fldName(fields[i].name);
				QString fldID( KexiUtils::string2Identifier(fldName) );

				KexiDB::Field *fld = 
				  new KexiDB::Field(fldID, type(originalName, &fields[i]));
				
				if(fld->type() == KexiDB::Field::Enum) {
					QStringList values = examineEnumField(originalName, &fields[i]);
				}
				
				fld->setCaption(fldName);
				getConstraints(fields[i].flags, fld);
				getOptions(fields[i].flags, fld);
				tableSchema.addField(fld);
			}
			mysql_free_result(res);
		} else {
			kdDebug() << "MySQLMigrate::drv_tableNames: null result" << endl;
		}
		return true;
	} else {
	  return false;
	}
}
コード例 #4
0
void KexiDataSourcePage::slotFieldSelected()
{
    KexiDB::Field::Type dataType = KexiDB::Field::InvalidType;
#ifdef KEXI_NO_AUTOFIELD_WIDGET
    KexiDB::Field *field = m_tableOrQuerySchema->field(
                               m_widgetDataSourceCombo->fieldOrExpression());  //temp
#else
//! @todo this should also work for expressions
    KexiDB::Field *field = m_fieldListView->schema()->field(
                               m_widgetDataSourceCombo->fieldOrExpression());
#endif
    if (field)
        dataType = field->type();

    emit dataSourceFieldOrExpressionChanged(
        m_widgetDataSourceCombo->fieldOrExpression(),
        m_widgetDataSourceCombo->fieldOrExpressionCaption(),
        dataType
    );
}
コード例 #5
0
bool OdbMigrate::drv_readTableSchema(
    const QString& originalName, KexiDB::TableSchema& tableSchema)
{
    char* tableName=originalName.toAscii().data();
    jmethodID getTableNames = env->GetMethodID(clsH,"getTableSchema","(Ljava/lang/String;)Ljava/lang/String;");
    jstring returnString = (jstring) env->CallObjectMethod(java_class_object,getTableNames,tableName);
    const char* tablesstring = env->GetStringUTFChars(returnString, NULL);
    QString jsonString(tablesstring);
    QStringList list = jsonString.split(",");

    for(int i=0;i<list.size();i+=2)
    {
        QString fldID(KexiUtils::stringToIdentifier(list.at(i+1)));
        KexiDB::Field *fld =
            new KexiDB::Field(fldID, type(list.at(i+1)));
        fld->setCaption(list.at(i));
        tableSchema.addField(fld);
    }

    return false;
}
コード例 #6
0
KexiTableEdit* KexiCellEditorFactory::createEditor(KexiTableViewColumn &column, QWidget* parent)
{
    KexiDB::Field *realField;
    if (column.visibleLookupColumnInfo()) {
        realField = column.visibleLookupColumnInfo()->field;
    } else {
        realField = column.field();
    }

    KexiCellEditorFactoryItem *item = 0;

    if (hasEnumType(column)) {
        //--we need to create combo box because of relationship:
        item = KexiCellEditorFactory::item(KexiDB::Field::Enum);
    } else {
        item = KexiCellEditorFactory::item(realField->type(), realField->subType());
    }

#if 0 //js: TODO LATER
    //--check if we need to create combo box because of relationship:
    //WARNING: it's assumed that indices are one-field long
    KexiDB::TableSchema *table = f.table();
    if (table) {
        //find index that contain this field
        KexiDB::IndexSchema::ListIterator it = table->indicesIterator();
        for (;it.current();++it) {
            KexiDB::IndexSchema *idx = it.current();
            if (idx->fields()->contains(&f)) {
                //find details-side rel. for this index
                KexiDB::Relationship *rel = idx->detailsRelationships()->first();
                if (rel) {

                }
            }
        }
    }
#endif

    return item->createEditor(column, parent);
}
コード例 #7
0
void KexiTableEdit::setupContents( QPainter *p, bool focused, const QVariant& val, 
	QString &txt, int &align, int &/*x*/, int &y_offset, int &w, int &h  )
{
	Q_UNUSED(p);
	Q_UNUSED(focused);
	Q_UNUSED(h);
	KexiDB::Field *realField = displayedField();

#ifdef Q_WS_WIN
//	x = 1;
	y_offset = -1;
#else
//	x = 1;
	y_offset = 0;
#endif

	if (realField->isFPNumericType()) {
//! @todo ADD OPTION to displaying NULL VALUES as e.g. "(null)"
		if (!val.isNull()) {
			txt = KexiDB::formatNumberForVisibleDecimalPlaces(
				val.toDouble(), realField->visibleDecimalPlaces());
		}
		w -= 6;
		align |= AlignRight;
	}
	else if (realField->isIntegerType()) {
		Q_LLONG num = val.toLongLong();
		w -= 6;
		align |= AlignRight;
		if (!val.isNull())
			txt = QString::number(num);
	}
	else {//default:
		if (!val.isNull()) {
			txt = val.toString();
		}
		align |= AlignLeft;
	}
}
コード例 #8
0
void KexiDataSourcePage::slotFieldSelected()
{
    KexiDB::Field::Type dataType = KexiDB::Field::InvalidType;
#ifdef KEXI_NO_AUTOFIELD_WIDGET
    KexiDB::Field *field = m_tableOrQuerySchema->field(
                               m_widgetDataSourceCombo->fieldOrExpression());  //temp
#else
//! @todo this should also work for expressions
    KexiDB::Field *field = m_fieldListView->schema()->field(
                               m_widgetDataSourceCombo->fieldOrExpression());
#endif
    if (field)
        dataType = field->type();

/*2.0: clear button is available in the combobox itself
    m_clearWidgetDSButton->setEnabled(!m_widgetDataSourceCombo->fieldOrExpression().isEmpty());*/

    emit dataSourceFieldOrExpressionChanged(
        m_widgetDataSourceCombo->fieldOrExpression(),
        m_widgetDataSourceCombo->fieldOrExpressionCaption(),
        dataType
    );
}
コード例 #9
0
//==================================================================================
//This is probably going to be quite complex...need to get the types for all columns
//any any other attributes required by kexi
//helped by reading the 'tables' test program
bool PqxxMigrate::drv_readTableSchema(
    const QString& originalName, KexiDB::TableSchema& tableSchema)
{
//    m_table = new KexiDB::TableSchema(table);

    //TODO IDEA: ask for user input for captions
//moved    m_table->setCaption(table + " table");

    //Perform a query on the table to get some data
    kDebug();
    tableSchema.setName(originalName);
    if (!query("select * from " + drv_escapeIdentifier(originalName) + " limit 1"))
        return false;
    //Loop round the fields
    for (uint i = 0; i < (uint)m_res->columns(); i++) {
        QString fldName(m_res->column_name(i));
        KexiDB::Field::Type fldType = type(m_res->column_type(i), fldName);
        QString fldID(KexiUtils::string2Identifier(fldName));
        const pqxx::oid toid = tableOid(originalName);
        if (toid == 0)
            return false;
        KexiDB::Field *f = new KexiDB::Field(fldID, fldType);
        f->setCaption(fldName);
        f->setPrimaryKey(primaryKey(toid, i));
        f->setUniqueKey(uniqueKey(toid, i));
        f->setAutoIncrement(autoInc(toid, i));//This should be safe for all field types
        tableSchema.addField(f);

        // Do this for var/char types
        //m_f->setLength(m_res->at(0)[i].size());

        // Do this for numeric type
        /*m_f->setScale(0);
        m_f->setPrecision(0);*/

        kDebug() << "Added field [" << f->name() << "] type [" << f->typeName()
        << ']';
    }
    return true;
}
コード例 #10
0
bool SQLitePreparedStatement::execute()
{
#ifdef SQLITE2
//! @todo
#else
	if (!prepared_st_handle)
		return false;
	if (m_resetRequired) {
		res = sqlite3_reset(prepared_st_handle);
		if (SQLITE_OK != res) {
			//! @todo msg?
			return false;
		}
		m_resetRequired = false;
	}

	int arg=1; //arg index counted from 1
	KexiDB::Field *field;

	Field::List _dummy;
	Field::ListIterator itFields(_dummy);
	//for INSERT, we're iterating over inserting values
	//for SELECT, we're iterating over WHERE conditions
	if (m_type == SelectStatement)
		itFields = *m_whereFields;
	else if (m_type == InsertStatement)
		itFields = m_fields->fieldsIterator();
	else
		assert(0); //impl. error

	for (QValueListConstIterator<QVariant> it = m_args.constBegin(); 
		(field = itFields.current()); ++it, ++itFields, arg++)
	{
		if (it==m_args.constEnd() || (*it).isNull()) {//no value to bind or the value is null: bind NULL
			res = sqlite3_bind_null(prepared_st_handle, arg);
			if (SQLITE_OK != res) {
				//! @todo msg?
				return false;
			}
			continue;
		}
		if (field->isTextType()) {
			//! @todo optimize: make a static copy so SQLITE_STATIC can be used
			QCString utf8String((*it).toString().utf8());
			res = sqlite3_bind_text(prepared_st_handle, arg, 
				(const char*)utf8String, utf8String.length(), SQLITE_TRANSIENT /*??*/);
			if (SQLITE_OK != res) {
				//! @todo msg?
				return false;
			}
		}
		else switch (field->type()) {
		case KexiDB::Field::Byte:
		case KexiDB::Field::ShortInteger:
		case KexiDB::Field::Integer:
		{
//! @todo what about unsigned > INT_MAX ?
			bool ok;
			const int value = (*it).toInt(&ok);
			if (ok) {
				res = sqlite3_bind_int(prepared_st_handle, arg, value);
				if (SQLITE_OK != res) {
					//! @todo msg?
					return false;
				}
			}
			else {
				res = sqlite3_bind_null(prepared_st_handle, arg);
				if (SQLITE_OK != res) {
					//! @todo msg?
					return false;
				}
			}
			break;
		}
		case KexiDB::Field::Float:
		case KexiDB::Field::Double:
			res = sqlite3_bind_double(prepared_st_handle, arg, (*it).toDouble());
			if (SQLITE_OK != res) {
				//! @todo msg?
				return false;
			}
			break;
		case KexiDB::Field::BigInteger:
		{
//! @todo what about unsigned > LLONG_MAX ?
			bool ok;
			Q_LLONG value = (*it).toLongLong(&ok);
			if (ok) {
				res = sqlite3_bind_int64(prepared_st_handle, arg, value);
				if (SQLITE_OK != res) {
					//! @todo msg?
					return false;
				}
			}
			else {
				res = sqlite3_bind_null(prepared_st_handle, arg);
				if (SQLITE_OK != res) {
					//! @todo msg?
					return false;
				}
			}
			break;
		}
		case KexiDB::Field::Boolean:
			res = sqlite3_bind_text(prepared_st_handle, arg, 
				QString::number((*it).toBool() ? 1 : 0).latin1(), 
				1, SQLITE_TRANSIENT /*??*/);
			if (SQLITE_OK != res) {
				//! @todo msg?
				return false;
			}
			break;
		case KexiDB::Field::Time:
			res = sqlite3_bind_text(prepared_st_handle, arg, 
				(*it).toTime().toString(Qt::ISODate).latin1(), 
				sizeof("HH:MM:SS"), SQLITE_TRANSIENT /*??*/);
			if (SQLITE_OK != res) {
				//! @todo msg?
				return false;
			}
			break;
		case KexiDB::Field::Date:
			res = sqlite3_bind_text(prepared_st_handle, arg, 
				(*it).toDate().toString(Qt::ISODate).latin1(), 
				sizeof("YYYY-MM-DD"), SQLITE_TRANSIENT /*??*/);
			if (SQLITE_OK != res) {
				//! @todo msg?
				return false;
			}
			break;
		case KexiDB::Field::DateTime:
			res = sqlite3_bind_text(prepared_st_handle, arg, 
				(*it).toDateTime().toString(Qt::ISODate).latin1(), 
				sizeof("YYYY-MM-DDTHH:MM:SS"), SQLITE_TRANSIENT /*??*/);
			if (SQLITE_OK != res) {
				//! @todo msg?
				return false;
			}
			break;
		case KexiDB::Field::BLOB:
		{
			const QByteArray byteArray((*it).toByteArray());
			res = sqlite3_bind_blob(prepared_st_handle, arg, 
				(const char*)byteArray, byteArray.size(), SQLITE_TRANSIENT /*??*/);
			if (SQLITE_OK != res) {
				//! @todo msg?
				return false;
			}
			break;
		}
		default:
			KexiDBWarn << "PreparedStatement::execute(): unsupported field type: " 
				<< field->type() << " - NULL value bound to column #" << arg << endl;
			res = sqlite3_bind_null(prepared_st_handle, arg);
			if (SQLITE_OK != res) {
				//! @todo msg?
				return false;
			}
		} //switch
	}

	//real execution
	res = sqlite3_step(prepared_st_handle);
	m_resetRequired = true;
	if (m_type == InsertStatement && res == SQLITE_DONE) {
		return true;
	}
	if (m_type == SelectStatement) {
		//fetch result

		//todo
	}
#endif
	return false;
}
コード例 #11
0
bool Authenticator::loadStore() {
    KexiDB::TableSchema* table = KexiWebForms::Model::gConnection->tableSchema("kexi__users");

    if (!table) {
        // the table doesn't exist, create it (programmatically)
        kDebug() << "kexi__users table does not exist, creating it";
        KexiDB::TableSchema* kexi__users = new KexiDB::TableSchema("kexi__users");
        kexi__users->setNative(true);
        KexiDB::Field* id = new KexiDB::Field("u_id", KexiDB::Field::Integer);
        id->setAutoIncrement(true);
        id->setPrimaryKey(true);
        kexi__users->insertField(0, id);
        KexiDB::Field* name = new KexiDB::Field("u_name", KexiDB::Field::Text);
        kexi__users->insertField(1, name);
        KexiDB::Field* password = new KexiDB::Field("u_password", KexiDB::Field::Text);
        kexi__users->insertField(2, password);
        KexiDB::Field* create = new KexiDB::Field("u_create", KexiDB::Field::Boolean);
        kexi__users->insertField(3, create);
        KexiDB::Field* read = new KexiDB::Field("u_read", KexiDB::Field::Boolean);
        kexi__users->insertField(4, read);
        KexiDB::Field* update = new KexiDB::Field("u_update", KexiDB::Field::Boolean);
        kexi__users->insertField(5, update);
        KexiDB::Field* fdelete = new KexiDB::Field("u_delete", KexiDB::Field::Boolean);
        kexi__users->insertField(6, fdelete);
        KexiDB::Field* fquery = new KexiDB::Field("u_query", KexiDB::Field::Boolean);
        kexi__users->insertField(7, fquery);

        if (!KexiWebForms::Model::gConnection->createTable(kexi__users)) {
            // Table was not created, fatal error
            kError() << "Failed to create system table kexi__users";
            kError() << "Error string: " << KexiWebForms::Model::gConnection->errorMsg();
            delete kexi__users;
            return false;
        } else {
            // Table was created, create two standard accounts
            KexiDB::QuerySchema query(*kexi__users);
            KexiDB::Cursor* cursor = KexiWebForms::Model::gConnection->prepareQuery(query);
            KexiDB::RecordData recordData(kexi__users->fieldCount());
            KexiDB::RowEditBuffer editBuffer(true);
            // root
            QVariant vtrue(true);
            QVariant vfalse(false);
            kDebug() << "Creating user root with password root";
            QVariant user_root("root");
            QVariant password_root("root");
            editBuffer.insert(*query.columnInfo(name->name()), user_root);
            editBuffer.insert(*query.columnInfo(password->name()), password_root);
            editBuffer.insert(*query.columnInfo(create->name()), vtrue);
            editBuffer.insert(*query.columnInfo(read->name()), vtrue);
            editBuffer.insert(*query.columnInfo(update->name()), vtrue);
            editBuffer.insert(*query.columnInfo(fdelete->name()), vtrue);
            editBuffer.insert(*query.columnInfo(fquery->name()), vtrue);
            kDebug() << "Registering user within database";
            if (cursor->insertRow(recordData, editBuffer)) {
                kDebug() << "Succeeded";
                User* u = new User("root", "root");
                m_users.append(*u);
                m_auth->addUser(u->name().toUtf8().constData(), u->password().toUtf8().constData());
            } else {
                kError() << "An error occurred";
                return false;
            }

            // anonymous
            kDebug() << "Creating user anonymous with password guest";
            QVariant user_anonymous("anonymous");
            QVariant password_anonymous("guest");
            editBuffer.insert(*query.columnInfo(name->name()), user_anonymous);
            editBuffer.insert(*query.columnInfo(password->name()), password_anonymous);
            editBuffer.insert(*query.columnInfo(create->name()), vfalse);
            editBuffer.insert(*query.columnInfo(read->name()), vfalse);
            editBuffer.insert(*query.columnInfo(update->name()), vfalse);
            editBuffer.insert(*query.columnInfo(fdelete->name()), vfalse);
            editBuffer.insert(*query.columnInfo(fquery->name()), vfalse);
            if (cursor->insertRow(recordData, editBuffer)) {
                kDebug() << "Succeeded";
                User* u = new User("anonymous", "guest");
                m_users.append(*u);
                m_auth->addUser(u->name().toUtf8().constData(), u->password().toUtf8().constData());
            } else {
                kError() << "An error occurred";
                return false;
            }
            KexiWebForms::Model::gConnection->deleteCursor(cursor);
        }
    } else {
        // load stuff from the store, create appropriated User objects, store them within
        // Authenticator
        KexiDB::QuerySchema query(*table);
        KexiDB::Cursor* cursor = KexiWebForms::Model::gConnection->executeQuery(query);
        while (cursor->moveNext()) {
            // Skip id
            QString* username = new QString(cursor->value(1).toString());
            QString* password = new QString(cursor->value(2).toString());
            QList<Permission>* perms = new QList<Permission>;

            if (cursor->value(3).toBool()) perms->append(CREATE);
            if (cursor->value(4).toBool()) perms->append(READ);
            if (cursor->value(5).toBool()) perms->append(UPDATE);
            if (cursor->value(6).toBool()) perms->append(DELETE);
            if (cursor->value(7).toBool()) perms->append(QUERY);

            User* u = new User(*username, *password, *perms);
            m_users.append(*u);
            m_auth->addUser(u->name().toUtf8().constData(), u->password().toUtf8().constData());
            kDebug() << "Loaded user " << *username << " from store";
        }
    }

    return true;
}
コード例 #12
0
ファイル: mdbmigrate.cpp プロジェクト: crayonink/calligra-2
bool MDBMigrate::getPrimaryKey(KexiDB::TableSchema* table, MdbTableDef* tableDef)
{
    MdbIndex *idx;

    if (!tableDef) {
        return false;
    }
    mdb_read_columns(tableDef);
    mdb_read_indices(tableDef);

    // Find the PK index in the MDB file
    bool foundIdx = false;
    for (unsigned int i = 0; i < tableDef->num_idxs; i++) {
        idx = (MdbIndex*) g_ptr_array_index(tableDef->indices, i);
//  QString fldName = QString::fromUtf8(idx->name);

        if (!strcmp(idx->name, "PrimaryKey")) {
            idx = (MdbIndex*) g_ptr_array_index(tableDef->indices, i);
            foundIdx = true;
            break;
        }
    }

    if (!foundIdx) {
        mdb_free_indices(tableDef->indices);
        return false;
    }

    //! @todo: MDB index order (asc, desc)

    kDebug() << "num_keys" << idx->num_keys;

    //! Create the KexiDB IndexSchema ...
    QVector<int> key_col_num(idx->num_keys);

    // MDBTools counts columns from 1 - subtract 1 where necessary
    KexiDB::IndexSchema* p_idx = new KexiDB::IndexSchema(table);

    for (unsigned int i = 0; i < idx->num_keys; i++) {
        key_col_num[i] = idx->key_col_num[i];
        kDebug() << "key" << i + 1 << " col " << key_col_num[i]
                 << table->field(idx->key_col_num[i] - 1)->name()
;
        p_idx->addField(table->field(idx->key_col_num[i] - 1));
    }

    kDebug() << p_idx->debugString();

    // ... and add it to the table definition
    // but only if the PK has only one field, so far :o(

    KexiDB::Field *f;
    if (idx->num_keys == 1 && (f = table->field(idx->key_col_num[0] - 1))) {
        f->setPrimaryKey(true);
    } else {
        //! @todo: How to add a composite PK to a TableSchema?
        //m_table->setPrimaryKey(p_idx);
    }

    mdb_free_indices(tableDef->indices);
    return true;
}