int nuodb_resultset_column_names(struct nuodb *db, struct nuodb_resultset *rs, struct nuodb_value names[]) { ResultSet *resultSet = reinterpret_cast<ResultSet *>(rs); try { ResultSetMetaData *resultSetMetaData = resultSet->getMetaData(); int columnCount = resultSetMetaData->getColumnCount(); for (int i=0; i < columnCount; ++i) { int columnIndex = i+1; const char *string = resultSetMetaData->getColumnLabel(columnIndex); names[i].i64 = reinterpret_cast<int64_t>(string); names[i].i32 = std::strlen(string); } return 0; } catch (SQLException &e) { return setError(db, e); } }
int nuodb_resultset_next(struct nuodb *db, struct nuodb_resultset *rs, int *has_values, struct nuodb_value values[]) { ResultSet *resultSet = reinterpret_cast<ResultSet *>(rs); try { *has_values = resultSet->next(); if (*has_values) { ResultSetMetaData *resultSetMetaData = resultSet->getMetaData(); int columnCount = resultSetMetaData->getColumnCount(); for (int i=0; i < columnCount; ++i) { int64_t i64 = 0; int32_t i32 = 0; enum nuodb_value_type vt = NUODB_TYPE_NULL; int columnIndex = i+1; switch (resultSetMetaData->getColumnType(columnIndex)) { case NUOSQL_NULL: vt = NUODB_TYPE_NULL; break; case NUOSQL_TINYINT: case NUOSQL_SMALLINT: case NUOSQL_INTEGER: case NUOSQL_BIGINT: if (resultSetMetaData->getScale(columnIndex) == 0) { i64 = resultSet->getLong(columnIndex); if (!resultSet->wasNull()) { vt = NUODB_TYPE_INT64; } break; } // fallthrough; must be fetched as a string case NUOSQL_NUMERIC: case NUOSQL_DECIMAL: { const char *string = resultSet->getString(columnIndex); if (!resultSet->wasNull()) { vt = NUODB_TYPE_BYTES; // strings are returned as bytes i64 = reinterpret_cast<int64_t>(string); i32 = std::strlen(string); } break; } case NUOSQL_FLOAT: case NUOSQL_DOUBLE: { union { double float64; int64_t i64; } value = { resultSet->getDouble(columnIndex) }; if (!resultSet->wasNull()) { vt = NUODB_TYPE_FLOAT64; i64 = value.i64; } break; } case NUOSQL_BIT: case NUOSQL_BOOLEAN: i64 = resultSet->getBoolean(columnIndex); if (!resultSet->wasNull()) { vt = NUODB_TYPE_BOOL; } break; case NUOSQL_DATE: case NUOSQL_TIME: case NUOSQL_TIMESTAMP: { Timestamp *ts = resultSet->getTimestamp(columnIndex); if (ts && !resultSet->wasNull()) { vt = NUODB_TYPE_TIME; i64 = ts->getSeconds(); i32 = ts->getNanos(); } break; } default: { const Bytes b = resultSet->getBytes(columnIndex); if (!resultSet->wasNull()) { vt = NUODB_TYPE_BYTES; i64 = reinterpret_cast<int64_t>(b.data); i32 = b.length; } break; } } values[i].i64 = i64; values[i].i32 = i32; values[i].vt = vt; } } return 0; } catch (SQLException &e) { return setError(db, e); } }
/** * * Executes a query and returns the result * * @param VariantVector arguments The query arguments. The first argument should * be the query and any subsequent arguments are the bind parameters * * @return The results from the query */ QueryResult DatabaseConnection::execute(VariantVector arguments) { int i; int count; QueryResult result; ResultSet *sqlResult; ResultSetMetaData *sqlMetadata; result = connect(); if (result.error.isError) { // There was an error connecting. Return the result. return result; } PreparedStatement *sqlStatement = nullptr; try { // Prepare query sqlStatement = connection->prepareStatement( arguments.front().toString()); if (arguments.size() > 1) { // Bind arguments int i = 1; for (auto it = arguments.begin() + 1; it != arguments.end(); ++it) { sqlStatement->setString(i, it->toString()); i++; } } // Execute query sqlStatement->execute(); // Fetch results sqlResult = sqlStatement->getResultSet(); } catch (SQLException &e) { if (sqlStatement != nullptr) { // Free memory delete sqlStatement; } result.error.isError = true; result.error.code = e.getErrorCode(); result.error.string = e.getSQLState() + ": " + e.what(); return result; } sqlMetadata = sqlResult->getMetaData(); count = sqlMetadata->getColumnCount(); for (i = 1; i <= count; i++) { // Add to collection result.columns.push_back(sqlMetadata->getColumnName(i).asStdString()); } // Read rows while (sqlResult->next()) { VariantVector row; for (i = 1; i <= count; i++) { Variant column; switch (sqlMetadata->getColumnType(i)) { default: case ::DataType::UNKNOWN: case ::DataType::CHAR: case ::DataType::VARCHAR: case ::DataType::LONGVARCHAR: case ::DataType::BINARY: case ::DataType::VARBINARY: case ::DataType::LONGVARBINARY: case ::DataType::TIMESTAMP: case ::DataType::DATE: case ::DataType::GEOMETRY: case ::DataType::ENUM: case ::DataType::SET: case ::DataType::BIGINT: case ::DataType::REAL: case ::DataType::DOUBLE: case ::DataType::DECIMAL: // @TODO: store binary, timestamp, date, & geometry differently // Also numeric types (need to be added to Variant class) column = sqlResult->getString(i).asStdString(); break; case ::DataType::SQLNULL: column = Variant(); break; case ::DataType::BIT: case ::DataType::TINYINT: case ::DataType::SMALLINT: case ::DataType::MEDIUMINT: case ::DataType::INTEGER: case ::DataType::NUMERIC: column = sqlResult->getInt(i); break; case ::DataType::YEAR: column = static_cast<unsigned short>(sqlResult->getUInt(i)); break; } // Add column to collection row.push_back(column); } // Add row to collection result.rows.push_back(row); } // Free memory delete sqlResult; delete sqlStatement; return result; }