Search in sources :

Example 11 with Row

use of io.vertx.sqlclient.Row in project raml-module-builder by folio-org.

the class PostgresClientIT method maxPoolSize.

/**
 * Each connection runs pg_sleep(1) that takes 1 second.
 * Setting maxPoolSize=90 runs them in parallel so that it
 * completes within 5 seconds.
 *
 * <p>If you want to test with a higher maxPoolSize you
 * need to increase max_connections so that maxPoolSize is within
 * (max_connections - superuser_reserved_connections):
 * <a href="https://www.postgresql.org/docs/current/runtime-config-connection.html">
 * https://www.postgresql.org/docs/current/runtime-config-connection.html</a>
 */
// milliseconds
@Test(timeout = 5000)
public void maxPoolSize(TestContext context) {
    int maxPoolSize = 90;
    postgresClient = createA(context, TENANT);
    JsonObject configuration = postgresClient.getConnectionConfig().copy().put("maxPoolSize", maxPoolSize);
    postgresClient.setClient(PostgresClient.createPgPool(vertx, configuration));
    List<Future> futures = new ArrayList<>();
    for (int i = 0; i < maxPoolSize; i++) {
        futures.add(Future.<RowSet<Row>>future(promise -> postgresClient.execute("SELECT pg_sleep(1)", promise)));
    }
    CompositeFuture.all(futures).onComplete(context.asyncAssertSuccess());
}
Also used : CoreMatchers.is(org.hamcrest.CoreMatchers.is) TestContext(io.vertx.ext.unit.TestContext) RowStream(io.vertx.sqlclient.RowStream) Arrays(java.util.Arrays) PgNotification(io.vertx.pgclient.PgNotification) TransactionRollbackException(io.vertx.sqlclient.TransactionRollbackException) VertxUtils(org.folio.rest.tools.utils.VertxUtils) Tuple(io.vertx.sqlclient.Tuple) UpdateSection(org.folio.rest.persist.Criteria.UpdateSection) CoreMatchers.instanceOf(org.hamcrest.CoreMatchers.instanceOf) RowIterator(io.vertx.sqlclient.RowIterator) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) SqlResult(io.vertx.sqlclient.SqlResult) After(org.junit.After) JsonObject(io.vertx.core.json.JsonObject) Offset(org.folio.rest.persist.Criteria.Offset) Collector(java.util.stream.Collector) Transaction(io.vertx.sqlclient.Transaction) AfterClass(org.junit.AfterClass) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) RowImpl(io.vertx.pgclient.impl.RowImpl) Set(java.util.Set) UUID(java.util.UUID) FieldException(org.folio.cql2pgjson.exception.FieldException) Future(io.vertx.core.Future) StandardCharsets(java.nio.charset.StandardCharsets) UncheckedIOException(java.io.UncheckedIOException) IOUtils(org.apache.commons.io.IOUtils) CQL2PgJSON(org.folio.cql2pgjson.CQL2PgJSON) Base64(java.util.Base64) List(java.util.List) Stream(java.util.stream.Stream) Criterion(org.folio.rest.persist.Criteria.Criterion) Results(org.folio.rest.persist.interfaces.Results) Facet(org.folio.rest.jaxrs.model.Facet) RowDesc(io.vertx.sqlclient.impl.RowDesc) Async(io.vertx.ext.unit.Async) CQLWrapper(org.folio.rest.persist.cql.CQLWrapper) BeforeClass(org.junit.BeforeClass) FacetField(org.folio.rest.persist.facets.FacetField) PostgresTesterContainer(org.folio.postgres.testing.PostgresTesterContainer) Criteria(org.folio.rest.persist.Criteria.Criteria) CoreMatchers.not(org.hamcrest.CoreMatchers.not) RunWith(org.junit.runner.RunWith) Timeout(io.vertx.ext.unit.junit.Timeout) ResultInfo(org.folio.rest.jaxrs.model.ResultInfo) Function(java.util.function.Function) TotaledResults(org.folio.rest.persist.PostgresClient.TotaledResults) ArrayList(java.util.ArrayList) PreparedStatement(io.vertx.sqlclient.PreparedStatement) HashSet(java.util.HashSet) CompositeFuture(io.vertx.core.CompositeFuture) Poline(org.folio.rest.persist.helpers.Poline) PrepareOptions(io.vertx.sqlclient.PrepareOptions) SqlConnection(io.vertx.sqlclient.SqlConnection) Limit(org.folio.rest.persist.Criteria.Limit) QueryHelper(org.folio.rest.persist.PostgresClient.QueryHelper) RowSet(io.vertx.sqlclient.RowSet) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) AsyncResult(io.vertx.core.AsyncResult) LinkedList(java.util.LinkedList) DatabaseMetadata(io.vertx.sqlclient.spi.DatabaseMetadata) CoreMatchers.nullValue(org.hamcrest.CoreMatchers.nullValue) Before(org.junit.Before) Files(java.nio.file.Files) Query(io.vertx.sqlclient.Query) Promise(io.vertx.core.Promise) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) Vertx(io.vertx.core.Vertx) PgPool(io.vertx.pgclient.PgPool) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) IOException(java.io.IOException) Test(org.junit.Test) VertxUnitRunner(io.vertx.ext.unit.junit.VertxUnitRunner) PreparedQuery(io.vertx.sqlclient.PreparedQuery) JsonArray(io.vertx.core.json.JsonArray) PgConnection(io.vertx.pgclient.PgConnection) Rule(org.junit.Rule) Paths(java.nio.file.Paths) Row(io.vertx.sqlclient.Row) LocalRowSet(org.folio.rest.persist.helpers.LocalRowSet) Handler(io.vertx.core.Handler) SimplePojo(org.folio.rest.persist.helpers.SimplePojo) Collections(java.util.Collections) InputStream(java.io.InputStream) ArrayList(java.util.ArrayList) JsonObject(io.vertx.core.json.JsonObject) Future(io.vertx.core.Future) CompositeFuture(io.vertx.core.CompositeFuture) Row(io.vertx.sqlclient.Row) Test(org.junit.Test)

Example 12 with Row

use of io.vertx.sqlclient.Row in project raml-module-builder by folio-org.

the class PostgresClientIT method saveBatchJson.

@Test
public void saveBatchJson(TestContext context) {
    String id = randomUuid();
    JsonArray array = new JsonArray().add("{ \"x\" : \"a\" }").add("{ \"y\" : \"z\", \"id\": \"" + id + "\" }").add("{ \"z\" : \"'\" }");
    createFoo(context).saveBatch(FOO, array, context.asyncAssertSuccess(res -> {
        // iterate over all RowSets in batch result to get total count
        RowSet<Row> resCurrent = res;
        int total = 0;
        while (resCurrent != null) {
            total += resCurrent.size();
            resCurrent = resCurrent.next();
        }
        context.assertEquals(3, total);
        context.assertEquals("id", res.columnsNames().get(0));
        // second set
        Row row = res.next().iterator().next();
        context.assertEquals(id, row.getValue("id").toString());
        postgresClient.getById(FOO, id, context.asyncAssertSuccess(get -> {
            context.assertEquals("z", get.getString("y"));
        }));
    }));
}
Also used : JsonArray(io.vertx.core.json.JsonArray) CoreMatchers.is(org.hamcrest.CoreMatchers.is) TestContext(io.vertx.ext.unit.TestContext) RowStream(io.vertx.sqlclient.RowStream) Arrays(java.util.Arrays) PgNotification(io.vertx.pgclient.PgNotification) TransactionRollbackException(io.vertx.sqlclient.TransactionRollbackException) VertxUtils(org.folio.rest.tools.utils.VertxUtils) Tuple(io.vertx.sqlclient.Tuple) UpdateSection(org.folio.rest.persist.Criteria.UpdateSection) CoreMatchers.instanceOf(org.hamcrest.CoreMatchers.instanceOf) RowIterator(io.vertx.sqlclient.RowIterator) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) SqlResult(io.vertx.sqlclient.SqlResult) After(org.junit.After) JsonObject(io.vertx.core.json.JsonObject) Offset(org.folio.rest.persist.Criteria.Offset) Collector(java.util.stream.Collector) Transaction(io.vertx.sqlclient.Transaction) AfterClass(org.junit.AfterClass) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) RowImpl(io.vertx.pgclient.impl.RowImpl) Set(java.util.Set) UUID(java.util.UUID) FieldException(org.folio.cql2pgjson.exception.FieldException) Future(io.vertx.core.Future) StandardCharsets(java.nio.charset.StandardCharsets) UncheckedIOException(java.io.UncheckedIOException) IOUtils(org.apache.commons.io.IOUtils) CQL2PgJSON(org.folio.cql2pgjson.CQL2PgJSON) Base64(java.util.Base64) List(java.util.List) Stream(java.util.stream.Stream) Criterion(org.folio.rest.persist.Criteria.Criterion) Results(org.folio.rest.persist.interfaces.Results) Facet(org.folio.rest.jaxrs.model.Facet) RowDesc(io.vertx.sqlclient.impl.RowDesc) Async(io.vertx.ext.unit.Async) CQLWrapper(org.folio.rest.persist.cql.CQLWrapper) BeforeClass(org.junit.BeforeClass) FacetField(org.folio.rest.persist.facets.FacetField) PostgresTesterContainer(org.folio.postgres.testing.PostgresTesterContainer) Criteria(org.folio.rest.persist.Criteria.Criteria) CoreMatchers.not(org.hamcrest.CoreMatchers.not) RunWith(org.junit.runner.RunWith) Timeout(io.vertx.ext.unit.junit.Timeout) ResultInfo(org.folio.rest.jaxrs.model.ResultInfo) Function(java.util.function.Function) TotaledResults(org.folio.rest.persist.PostgresClient.TotaledResults) ArrayList(java.util.ArrayList) PreparedStatement(io.vertx.sqlclient.PreparedStatement) HashSet(java.util.HashSet) CompositeFuture(io.vertx.core.CompositeFuture) Poline(org.folio.rest.persist.helpers.Poline) PrepareOptions(io.vertx.sqlclient.PrepareOptions) SqlConnection(io.vertx.sqlclient.SqlConnection) Limit(org.folio.rest.persist.Criteria.Limit) QueryHelper(org.folio.rest.persist.PostgresClient.QueryHelper) RowSet(io.vertx.sqlclient.RowSet) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) AsyncResult(io.vertx.core.AsyncResult) LinkedList(java.util.LinkedList) DatabaseMetadata(io.vertx.sqlclient.spi.DatabaseMetadata) CoreMatchers.nullValue(org.hamcrest.CoreMatchers.nullValue) Before(org.junit.Before) Files(java.nio.file.Files) Query(io.vertx.sqlclient.Query) Promise(io.vertx.core.Promise) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) Vertx(io.vertx.core.Vertx) PgPool(io.vertx.pgclient.PgPool) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) IOException(java.io.IOException) Test(org.junit.Test) VertxUnitRunner(io.vertx.ext.unit.junit.VertxUnitRunner) PreparedQuery(io.vertx.sqlclient.PreparedQuery) JsonArray(io.vertx.core.json.JsonArray) PgConnection(io.vertx.pgclient.PgConnection) Rule(org.junit.Rule) Paths(java.nio.file.Paths) Row(io.vertx.sqlclient.Row) LocalRowSet(org.folio.rest.persist.helpers.LocalRowSet) Handler(io.vertx.core.Handler) SimplePojo(org.folio.rest.persist.helpers.SimplePojo) Collections(java.util.Collections) InputStream(java.io.InputStream) RowSet(io.vertx.sqlclient.RowSet) LocalRowSet(org.folio.rest.persist.helpers.LocalRowSet) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) Row(io.vertx.sqlclient.Row) Test(org.junit.Test)

Example 13 with Row

use of io.vertx.sqlclient.Row in project raml-module-builder by folio-org.

the class PostgresClientIT method selectReturnEmptySet.

@Test
public void selectReturnEmptySet(TestContext context) {
    RowSet rowSet = new LocalRowSet(0);
    Promise<RowSet<Row>> promise = Promise.promise();
    promise.complete(rowSet);
    PostgresClient.selectReturn(promise.future(), context.asyncAssertSuccess(res -> context.assertEquals(null, res)));
}
Also used : CoreMatchers.is(org.hamcrest.CoreMatchers.is) TestContext(io.vertx.ext.unit.TestContext) RowStream(io.vertx.sqlclient.RowStream) Arrays(java.util.Arrays) PgNotification(io.vertx.pgclient.PgNotification) TransactionRollbackException(io.vertx.sqlclient.TransactionRollbackException) VertxUtils(org.folio.rest.tools.utils.VertxUtils) Tuple(io.vertx.sqlclient.Tuple) UpdateSection(org.folio.rest.persist.Criteria.UpdateSection) CoreMatchers.instanceOf(org.hamcrest.CoreMatchers.instanceOf) RowIterator(io.vertx.sqlclient.RowIterator) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) SqlResult(io.vertx.sqlclient.SqlResult) After(org.junit.After) JsonObject(io.vertx.core.json.JsonObject) Offset(org.folio.rest.persist.Criteria.Offset) Collector(java.util.stream.Collector) Transaction(io.vertx.sqlclient.Transaction) AfterClass(org.junit.AfterClass) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) RowImpl(io.vertx.pgclient.impl.RowImpl) Set(java.util.Set) UUID(java.util.UUID) FieldException(org.folio.cql2pgjson.exception.FieldException) Future(io.vertx.core.Future) StandardCharsets(java.nio.charset.StandardCharsets) UncheckedIOException(java.io.UncheckedIOException) IOUtils(org.apache.commons.io.IOUtils) CQL2PgJSON(org.folio.cql2pgjson.CQL2PgJSON) Base64(java.util.Base64) List(java.util.List) Stream(java.util.stream.Stream) Criterion(org.folio.rest.persist.Criteria.Criterion) Results(org.folio.rest.persist.interfaces.Results) Facet(org.folio.rest.jaxrs.model.Facet) RowDesc(io.vertx.sqlclient.impl.RowDesc) Async(io.vertx.ext.unit.Async) CQLWrapper(org.folio.rest.persist.cql.CQLWrapper) BeforeClass(org.junit.BeforeClass) FacetField(org.folio.rest.persist.facets.FacetField) PostgresTesterContainer(org.folio.postgres.testing.PostgresTesterContainer) Criteria(org.folio.rest.persist.Criteria.Criteria) CoreMatchers.not(org.hamcrest.CoreMatchers.not) RunWith(org.junit.runner.RunWith) Timeout(io.vertx.ext.unit.junit.Timeout) ResultInfo(org.folio.rest.jaxrs.model.ResultInfo) Function(java.util.function.Function) TotaledResults(org.folio.rest.persist.PostgresClient.TotaledResults) ArrayList(java.util.ArrayList) PreparedStatement(io.vertx.sqlclient.PreparedStatement) HashSet(java.util.HashSet) CompositeFuture(io.vertx.core.CompositeFuture) Poline(org.folio.rest.persist.helpers.Poline) PrepareOptions(io.vertx.sqlclient.PrepareOptions) SqlConnection(io.vertx.sqlclient.SqlConnection) Limit(org.folio.rest.persist.Criteria.Limit) QueryHelper(org.folio.rest.persist.PostgresClient.QueryHelper) RowSet(io.vertx.sqlclient.RowSet) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) AsyncResult(io.vertx.core.AsyncResult) LinkedList(java.util.LinkedList) DatabaseMetadata(io.vertx.sqlclient.spi.DatabaseMetadata) CoreMatchers.nullValue(org.hamcrest.CoreMatchers.nullValue) Before(org.junit.Before) Files(java.nio.file.Files) Query(io.vertx.sqlclient.Query) Promise(io.vertx.core.Promise) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) Vertx(io.vertx.core.Vertx) PgPool(io.vertx.pgclient.PgPool) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) IOException(java.io.IOException) Test(org.junit.Test) VertxUnitRunner(io.vertx.ext.unit.junit.VertxUnitRunner) PreparedQuery(io.vertx.sqlclient.PreparedQuery) JsonArray(io.vertx.core.json.JsonArray) PgConnection(io.vertx.pgclient.PgConnection) Rule(org.junit.Rule) Paths(java.nio.file.Paths) Row(io.vertx.sqlclient.Row) LocalRowSet(org.folio.rest.persist.helpers.LocalRowSet) Handler(io.vertx.core.Handler) SimplePojo(org.folio.rest.persist.helpers.SimplePojo) Collections(java.util.Collections) InputStream(java.io.InputStream) LocalRowSet(org.folio.rest.persist.helpers.LocalRowSet) RowSet(io.vertx.sqlclient.RowSet) LocalRowSet(org.folio.rest.persist.helpers.LocalRowSet) Test(org.junit.Test)

Example 14 with Row

use of io.vertx.sqlclient.Row in project raml-module-builder by folio-org.

the class PostgresClientIT method postgresClientQueryFails.

/**
 * @return a PostgresClient where invoking SQLConnection::update, SQLConnection::updateWithParams or
 * SQLConnection::queryWithParams will report a failure via the resultHandler.
 */
private PostgresClient postgresClientQueryFails() {
    PgConnection pgConnection = new PgConnection() {

        @Override
        public PgConnection notificationHandler(Handler<PgNotification> handler) {
            return this;
        }

        @Override
        public PgConnection cancelRequest(Handler<AsyncResult<Void>> handler) {
            handler.handle(Future.failedFuture("cancelRequestFails"));
            return this;
        }

        @Override
        public int processId() {
            return 0;
        }

        @Override
        public int secretKey() {
            return 0;
        }

        @Override
        public PgConnection prepare(String s, Handler<AsyncResult<PreparedStatement>> handler) {
            prepare(s).onComplete(handler);
            return null;
        }

        @Override
        public Future<PreparedStatement> prepare(String s) {
            return Future.failedFuture("preparedFails");
        }

        @Override
        public SqlConnection prepare(String sql, PrepareOptions options, Handler<AsyncResult<PreparedStatement>> handler) {
            prepare(sql, options).onComplete(handler);
            return null;
        }

        @Override
        public Future<PreparedStatement> prepare(String sql, PrepareOptions options) {
            return prepare(sql);
        }

        @Override
        public PgConnection exceptionHandler(Handler<Throwable> handler) {
            return null;
        }

        @Override
        public PgConnection closeHandler(Handler<Void> handler) {
            return null;
        }

        @Override
        public void begin(Handler<AsyncResult<Transaction>> handler) {
        }

        @Override
        public Future<Transaction> begin() {
            return null;
        }

        @Override
        public boolean isSSL() {
            return false;
        }

        @Override
        public void close(Handler<AsyncResult<Void>> handler) {
        }

        @Override
        public Query<RowSet<Row>> query(String s) {
            return new Query<RowSet<Row>>() {

                @Override
                public void execute(Handler<AsyncResult<RowSet<Row>>> handler) {
                    handler.handle(execute());
                }

                @Override
                public Future<RowSet<Row>> execute() {
                    return Future.failedFuture("queryFails");
                }

                @Override
                public <R> Query<SqlResult<R>> collecting(Collector<Row, ?, R> collector) {
                    return null;
                }

                @Override
                public <U> Query<RowSet<U>> mapping(Function<Row, U> function) {
                    return null;
                }
            };
        }

        @Override
        public PreparedQuery<RowSet<Row>> preparedQuery(String sql, PrepareOptions options) {
            return preparedQuery(sql);
        }

        @Override
        public PreparedQuery<RowSet<Row>> preparedQuery(String s) {
            throw new RuntimeException("queryFails");
        }

        @Override
        public Future<Void> close() {
            return null;
        }

        @Override
        public DatabaseMetadata databaseMetadata() {
            return null;
        }
    };
    PgPool client = new PgPoolBase() {

        @Override
        public Future<SqlConnection> getConnection() {
            return Future.succeededFuture(pgConnection);
        }
    };
    try {
        PostgresClient postgresClient = new PostgresClient(vertx, TENANT);
        postgresClient.setClient(client);
        return postgresClient;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
Also used : SqlResult(io.vertx.sqlclient.SqlResult) Query(io.vertx.sqlclient.Query) PreparedQuery(io.vertx.sqlclient.PreparedQuery) PgPool(io.vertx.pgclient.PgPool) PgConnection(io.vertx.pgclient.PgConnection) RowSet(io.vertx.sqlclient.RowSet) LocalRowSet(org.folio.rest.persist.helpers.LocalRowSet) Handler(io.vertx.core.Handler) PreparedStatement(io.vertx.sqlclient.PreparedStatement) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) TransactionRollbackException(io.vertx.sqlclient.TransactionRollbackException) FieldException(org.folio.cql2pgjson.exception.FieldException) UncheckedIOException(java.io.UncheckedIOException) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) IOException(java.io.IOException) Function(java.util.function.Function) Transaction(io.vertx.sqlclient.Transaction) PrepareOptions(io.vertx.sqlclient.PrepareOptions) Collector(java.util.stream.Collector) SqlConnection(io.vertx.sqlclient.SqlConnection) Row(io.vertx.sqlclient.Row)

Example 15 with Row

use of io.vertx.sqlclient.Row in project raml-module-builder by folio-org.

the class PostgresClientTest method getMockTestJsonbPojoResultSet.

private RowSet<Row> getMockTestJsonbPojoResultSet(int total) {
    List<String> columnNames = new ArrayList<String>(Arrays.asList(new String[] { "jsonb" }));
    RowDesc rowDesc = new RowDesc(columnNames);
    List<String> baz = new ArrayList<String>(Arrays.asList(new String[] { "This", "is", "a", "test" }));
    List<Row> rows = new LinkedList<>();
    for (int i = 0; i < total; i++) {
        Row row = new RowImpl(rowDesc);
        row.addValue(new JsonObject().put("id", UUID.randomUUID().toString()).put("foo", "foo " + i).put("bar", "bar " + i).put("biz", (double) i).put("baz", baz));
        rows.add(row);
    }
    return new LocalRowSet(total).withColumns(columnNames).withRows(rows);
}
Also used : RowImpl(io.vertx.pgclient.impl.RowImpl) LocalRowSet(org.folio.rest.persist.helpers.LocalRowSet) ArrayList(java.util.ArrayList) JsonObject(io.vertx.core.json.JsonObject) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) Row(io.vertx.sqlclient.Row) RowDesc(io.vertx.sqlclient.impl.RowDesc) LinkedList(java.util.LinkedList)

Aggregations

Row (io.vertx.sqlclient.Row)22 PgPool (io.vertx.pgclient.PgPool)12 ArrayList (java.util.ArrayList)11 JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)10 IOException (java.io.IOException)10 PgConnection (io.vertx.pgclient.PgConnection)9 RowSet (io.vertx.sqlclient.RowSet)9 SqlConnection (io.vertx.sqlclient.SqlConnection)9 Transaction (io.vertx.sqlclient.Transaction)9 LinkedList (java.util.LinkedList)9 CoreMatchers.containsString (org.hamcrest.CoreMatchers.containsString)9 Handler (io.vertx.core.Handler)8 RowImpl (io.vertx.pgclient.impl.RowImpl)8 PreparedStatement (io.vertx.sqlclient.PreparedStatement)8 Tuple (io.vertx.sqlclient.Tuple)8 RowDesc (io.vertx.sqlclient.impl.RowDesc)8 LocalRowSet (org.folio.rest.persist.helpers.LocalRowSet)8 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)7 AsyncResult (io.vertx.core.AsyncResult)7 Future (io.vertx.core.Future)7