diff --git a/pom.xml b/pom.xml index 1f1188a..8a72253 100644 --- a/pom.xml +++ b/pom.xml @@ -18,13 +18,14 @@ 2.22.1 1.82 - 2.1.11 + 2.2.0-SNAPSHOT auth secondary_index basic_example + query-example ydb-cookbook url-shortener-demo jdbc diff --git a/query-example/pom.xml b/query-example/pom.xml new file mode 100644 index 0000000..b95c969 --- /dev/null +++ b/query-example/pom.xml @@ -0,0 +1,88 @@ + + + 4.0.0 + + + tech.ydb.examples + ydb-sdk-examples + 1.1.0-SNAPSHOT + + + ydb-query-example + YDB QueryClient basic example + Simple example of usage QueryClient of Java SDK for YDB + + + 5.10.1 + + + + + tech.ydb + ydb-sdk-query + + + tech.ydb + ydb-sdk-topic + + + tech.ydb.auth + yc-auth-provider + + + + org.apache.logging.log4j + log4j-slf4j-impl + + + + tech.ydb.test + ydb-junit5-support + test + + + + org.junit.jupiter + junit-jupiter-api + ${junit5.version} + test + + + + + ydb-basic-example + + + + org.apache.maven.plugins + maven-dependency-plugin + + + + org.apache.maven.plugins + maven-jar-plugin + + + + true + libs/ + tech.ydb.example.App + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + cr.yandex/yc/yandex-docker-local-ydb:trunk + true + 1 + + + + + + diff --git a/query-example/src/main/java/tech/ydb/example/App.java b/query-example/src/main/java/tech/ydb/example/App.java new file mode 100644 index 0000000..bab6d2b --- /dev/null +++ b/query-example/src/main/java/tech/ydb/example/App.java @@ -0,0 +1,374 @@ +package tech.ydb.example; + +import java.io.IOException; +import java.time.Instant; +import java.time.LocalDate; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import tech.ydb.auth.iam.CloudAuthHelper; +import tech.ydb.core.Status; +import tech.ydb.core.grpc.GrpcTransport; +import tech.ydb.query.QueryClient; +import tech.ydb.query.QueryStream; +import tech.ydb.query.QueryTransaction; +import tech.ydb.query.QueryTx; +import tech.ydb.query.tools.QueryReader; +import tech.ydb.query.tools.SessionRetryContext; +import tech.ydb.table.query.Params; +import tech.ydb.table.result.ResultSetReader; +import tech.ydb.table.values.ListType; +import tech.ydb.table.values.ListValue; +import tech.ydb.table.values.PrimitiveType; +import tech.ydb.table.values.PrimitiveValue; +import tech.ydb.table.values.StructType; + + +public final class App implements Runnable, AutoCloseable { + private static final Logger logger = LoggerFactory.getLogger(App.class); + + private final GrpcTransport transport; + private final QueryClient queryClient; + private final SessionRetryContext retryCtx; + + App(String connectionString) { + this.transport = GrpcTransport.forConnectionString(connectionString) + .withAuthProvider(CloudAuthHelper.getAuthProviderFromEnviron()) + .build(); + this.queryClient = QueryClient.newClient(transport).build(); + this.retryCtx = SessionRetryContext.create(queryClient).build(); + } + + @Override + public void run() { + createTables(); + upsertTablesData(); + + upsertSimple(); + + selectSimple(); + selectWithParams(1, 2); + asyncSelectRead(2, 1); + + multiStepTransaction(2, 5); + tclTransaction(); + + dropTables(); + } + + @Override + public void close() { + queryClient.close(); + transport.close(); + } + + private void createTables() { + retryCtx.supplyResult(session -> session.createQuery("" + + "CREATE TABLE series (" + + " series_id UInt64," + + " title Text," + + " series_info Text," + + " release_date Date," + + " PRIMARY KEY(series_id)" + + ")", QueryTx.NONE).execute() + ).join().getStatus().expectSuccess("Can't create table series"); + + retryCtx.supplyResult(session -> session.createQuery("" + + "CREATE TABLE seasons (" + + " series_id UInt64," + + " season_id UInt64," + + " title Text," + + " first_aired Date," + + " last_aired Date," + + " PRIMARY KEY(series_id, season_id)" + + ")", QueryTx.NONE).execute() + ).join().getStatus().expectSuccess("Can't create table seasons"); + + retryCtx.supplyResult(session -> session.createQuery("" + + "CREATE TABLE episodes (" + + " series_id UInt64," + + " season_id UInt64," + + " episode_id UInt64," + + " title Text," + + " air_date Date," + + " PRIMARY KEY(series_id, season_id, episode_id)" + + ")", QueryTx.NONE).execute() + ).join().getStatus().expectSuccess("Can't create table episodes"); + } + + private void upsertTablesData() { + // Create type for struct of series + StructType seriesType = StructType.of( + "series_id", PrimitiveType.Uint64, + "title", PrimitiveType.Text, + "release_date", PrimitiveType.Date, + "series_info", PrimitiveType.Text + ); + // Create and fill list of series + ListValue seriesData = ListType.of(seriesType).newValue( + SeriesData.SERIES.stream().map(series -> seriesType.newValue( + "series_id", PrimitiveValue.newUint64(series.seriesID()), + "title", PrimitiveValue.newText(series.title()), + "release_date", PrimitiveValue.newDate(series.releaseDate()), + "series_info", PrimitiveValue.newText(series.seriesInfo()) + )).collect(Collectors.toList()) + ); + + // Upsert list of series to table + retryCtx.supplyResult(session -> session.createQuery( + "UPSERT INTO series SELECT * FROM AS_TABLE($values)", + QueryTx.SERIALIZABLE_RW, + Params.of("$values", seriesData) + ).execute()).join().getStatus().expectSuccess("upsert problem"); + + + // Create type for struct of season + StructType seasonType = StructType.of( + "series_id", PrimitiveType.Uint64, + "season_id", PrimitiveType.Uint64, + "title", PrimitiveType.Text, + "first_aired", PrimitiveType.Date, + "last_aired", PrimitiveType.Date + ); + // Create and fill list of seasons + ListValue seasonsData = ListType.of(seasonType).newValue( + SeriesData.SEASONS.stream().map(season -> seasonType.newValue( + "series_id", PrimitiveValue.newUint64(season.seriesID()), + "season_id", PrimitiveValue.newUint64(season.seasonID()), + "title", PrimitiveValue.newText(season.title()), + "first_aired", PrimitiveValue.newDate(season.firstAired()), + "last_aired", PrimitiveValue.newDate(season.lastAired()) + )).collect(Collectors.toList()) + ); + + // Upsert list of seasons to table + retryCtx.supplyResult(session -> session.createQuery( + "UPSERT INTO seasons SELECT * FROM AS_TABLE($values)", + QueryTx.SERIALIZABLE_RW, + Params.of("$values", seasonsData) + ).execute()).join().getStatus().expectSuccess("upsert problem"); + + + // Create type for struct of episode + StructType episodeType = StructType.of( + "series_id", PrimitiveType.Uint64, + "season_id", PrimitiveType.Uint64, + "episode_id", PrimitiveType.Uint64, + "title", PrimitiveType.Text, + "air_date", PrimitiveType.Date + ); + // Create and fill list of episodes + ListValue episodesData = ListType.of(episodeType).newValue( + SeriesData.EPISODES.stream().map(episode -> episodeType.newValue( + "series_id", PrimitiveValue.newUint64(episode.seriesID()), + "season_id", PrimitiveValue.newUint64(episode.seasonID()), + "episode_id", PrimitiveValue.newUint64(episode.episodeID()), + "title", PrimitiveValue.newText(episode.title()), + "air_date", PrimitiveValue.newDate(episode.airDate()) + )).collect(Collectors.toList()) + ); + + // Upsert list of series to episodes + retryCtx.supplyResult(session -> session.createQuery( + "UPSERT INTO episodes SELECT * FROM AS_TABLE($values)", + QueryTx.SERIALIZABLE_RW, + Params.of("$values", episodesData) + ).execute()).join().getStatus().expectSuccess("upsert problem"); + } + + private void upsertSimple() { + String query + = "UPSERT INTO episodes (series_id, season_id, episode_id, title) " + + "VALUES (2, 6, 1, \"TBD\");"; + + // Executes data query with specified transaction control settings. + retryCtx.supplyResult(session -> session.createQuery(query, QueryTx.SERIALIZABLE_RW).execute()) + .join().getValue(); + } + + private void selectSimple() { + String query + = "SELECT series_id, title, release_date " + + "FROM series WHERE series_id = 1;"; + + // Executes data query with specified transaction control settings. + QueryReader result = retryCtx.supplyResult( + session -> QueryReader.readFrom(session.createQuery(query, QueryTx.SERIALIZABLE_RW)) + ).join().getValue(); + + logger.info("--[ SelectSimple ]--"); + + ResultSetReader rs = result.getResultSet(0); + while (rs.next()) { + logger.info("read series with id {}, title {} and release_date {}", + rs.getColumn("series_id").getUint64(), + rs.getColumn("title").getText(), + rs.getColumn("release_date").getDate() + ); + } + } + + private void selectWithParams(long seriesID, long seasonID) { + String query + = "DECLARE $seriesId AS Uint64; " + + "DECLARE $seasonId AS Uint64; " + + "SELECT sa.title AS season_title, sr.title AS series_title " + + "FROM seasons AS sa INNER JOIN series AS sr ON sa.series_id = sr.series_id " + + "WHERE sa.series_id = $seriesId AND sa.season_id = $seasonId"; + + // Type of parameter values should be exactly the same as in DECLARE statements. + Params params = Params.of( + "$seriesId", PrimitiveValue.newUint64(seriesID), + "$seasonId", PrimitiveValue.newUint64(seasonID) + ); + + QueryReader result = retryCtx.supplyResult( + session -> QueryReader.readFrom(session.createQuery(query, QueryTx.SNAPSHOT_RO, params)) + ).join().getValue(); + + logger.info("--[ SelectWithParams ] -- "); + + ResultSetReader rs = result.getResultSet(0); + while (rs.next()) { + logger.info("read season with title {} for series {}", + rs.getColumn("season_title").getText(), + rs.getColumn("series_title").getText() + ); + } + } + + private void asyncSelectRead(long seriesID, long seasonID) { + String query + = "DECLARE $seriesId AS Uint64; " + + "DECLARE $seasonId AS Uint64; " + + "SELECT ep.title AS episode_title, sa.title AS season_title, sr.title AS series_title " + + "FROM episodes AS ep " + + "JOIN seasons AS sa ON sa.season_id = ep.season_id " + + "JOIN series AS sr ON sr.series_id = sa.series_id " + + "WHERE sa.series_id = $seriesId AND sa.season_id = $seasonId;"; + + // Type of parameter values should be exactly the same as in DECLARE statements. + Params params = Params.of( + "$seriesId", PrimitiveValue.newUint64(seriesID), + "$seasonId", PrimitiveValue.newUint64(seasonID) + ); + + logger.info("--[ ExecuteAsyncQueryWithParams ]--"); + retryCtx.supplyResult(session -> { + QueryStream asyncQuery = session.createQuery(query, QueryTx.SNAPSHOT_RO, params); + return asyncQuery.execute(part -> { + ResultSetReader rs = part.getResultSetReader(); + logger.info("read {} rows of result set {}", rs.getRowCount(), part.getResultSetIndex()); + while (rs.next()) { + logger.info("read episode {} of {} for {}", + rs.getColumn("episode_title").getText(), + rs.getColumn("season_title").getText(), + rs.getColumn("series_title").getText() + ); + } + }); + }).join().getStatus().expectSuccess("execute query problem"); + } + + private void multiStepTransaction(long seriesID, long seasonID) { + retryCtx.supplyStatus(session -> { + QueryTransaction transaction = session.createNewTransaction(QueryTx.SNAPSHOT_RO); + String query1 + = "DECLARE $seriesId AS Uint64; " + + "DECLARE $seasonId AS Uint64; " + + "SELECT MIN(first_aired) AS from_date FROM seasons " + + "WHERE series_id = $seriesId AND season_id = $seasonId;"; + + // Execute first query to start a new transaction + QueryReader res1 = QueryReader.readFrom(transaction.createQuery(query1, Params.of( + "$seriesId", PrimitiveValue.newUint64(seriesID), + "$seasonId", PrimitiveValue.newUint64(seasonID) + ))).join().getValue(); + + // Perform some client logic on returned values + ResultSetReader resultSet = res1.getResultSet(0); + if (!resultSet.next()) { + throw new RuntimeException("not found first_aired"); + } + LocalDate fromDate = resultSet.getColumn("from_date").getDate(); + LocalDate toDate = fromDate.plusDays(15); + + // Get active transaction id + logger.info("started new transaction {}", transaction.getId()); + + // Construct next query based on the results of client logic + String query2 + = "DECLARE $seriesId AS Uint64;" + + "DECLARE $fromDate AS Date;" + + "DECLARE $toDate AS Date;" + + "SELECT season_id, episode_id, title, air_date FROM episodes " + + "WHERE series_id = $seriesId AND air_date >= $fromDate AND air_date <= $toDate;"; + + // Execute second query with commit at end. + QueryReader res2 = QueryReader.readFrom(transaction.createQueryWithCommit(query2, Params.of( + "$seriesId", PrimitiveValue.newUint64(seriesID), + "$fromDate", PrimitiveValue.newDate(fromDate), + "$toDate", PrimitiveValue.newDate(toDate) + ))).join().getValue(); + + logger.info("--[ MultiStep ]--"); + ResultSetReader rs = res2.getResultSet(0); + while (rs.next()) { + logger.info("read episode {} with air date {}", + rs.getColumn("title").getText(), + rs.getColumn("air_date").getDate() + ); + } + + return CompletableFuture.completedFuture(Status.SUCCESS); + }).join().expectSuccess("multistep transaction problem"); + } + + private void tclTransaction() { + retryCtx.supplyResult(session -> { + QueryTransaction transaction = session.beginTransaction(QueryTx.SERIALIZABLE_RW) + .join().getValue(); + + String query + = "DECLARE $airDate AS Date; " + + "UPDATE episodes SET air_date = $airDate WHERE title = \"TBD\";"; + + Params params = Params.of("$airDate", PrimitiveValue.newDate(Instant.now())); + + // Execute data query. + // Transaction control settings continues active transaction (tx) + QueryReader reader = QueryReader.readFrom(transaction.createQuery(query, params)) + .join().getValue(); + + logger.info("get transaction {}", transaction.getId()); + + // Commit active transaction (tx) + return transaction.commit(); + }).join().getStatus().expectSuccess("tcl transaction problem"); + } + + private void dropTables() { + retryCtx.supplyResult(session -> session.createQuery("DROP TABLE episodes;", QueryTx.NONE).execute()) + .join().getStatus().expectSuccess("drop table episodes problem"); + retryCtx.supplyResult(session -> session.createQuery("DROP TABLE seasons;", QueryTx.NONE).execute()) + .join().getStatus().expectSuccess("drop table seasons problem"); + retryCtx.supplyResult(session -> session.createQuery("DROP TABLE series;", QueryTx.NONE).execute()) + .join().getStatus().expectSuccess("drop table series problem"); + } + + public static void main(String[] args) throws IOException { + if (args.length != 1) { + System.err.println("Usage: java -jar ydb-basic-example.jar "); + return; + } + + try (App app = new App(args[0])) { + app.run(); + } catch (Exception e) { + logger.error("app problem", e); + } + } +} diff --git a/query-example/src/main/java/tech/ydb/example/SeriesData.java b/query-example/src/main/java/tech/ydb/example/SeriesData.java new file mode 100644 index 0000000..f047a2d --- /dev/null +++ b/query-example/src/main/java/tech/ydb/example/SeriesData.java @@ -0,0 +1,114 @@ +package tech.ydb.example; + +import java.time.Instant; +import java.util.Arrays; +import java.util.List; + +import tech.ydb.example.model.Episode; +import tech.ydb.example.model.Season; +import tech.ydb.example.model.Series; + + +final class SeriesData { + public static final List SERIES = Arrays.asList( + new Series( + 1, "IT Crowd", date("2006-02-03"), + "The IT Crowd is a British sitcom produced by Channel 4, written by Graham Linehan, produced by " + + "Ash Atalla and starring Chris O'Dowd, Richard Ayoade, Katherine Parkinson, and Matt Berry."), + new Series( + 2, "Silicon Valley", date("2014-04-06"), + "Silicon Valley is an American comedy television series created by Mike Judge, John Altschuler and " + + "Dave Krinsky. The series focuses on five young men who founded a startup company in Silicon Valley.") + ); + + public static final List SEASONS = Arrays.asList( + new Season(1, 1, "Season 1", date("2006-02-03"), date("2006-03-03")), + new Season(1, 2, "Season 2", date("2007-08-24"), date("2007-09-28")), + new Season(1, 3, "Season 3", date("2008-11-21"), date("2008-12-26")), + new Season(1, 4, "Season 4", date("2010-06-25"), date("2010-07-30")), + new Season(2, 1, "Season 1", date("2014-04-06"), date("2014-06-01")), + new Season(2, 2, "Season 2", date("2015-04-12"), date("2015-06-14")), + new Season(2, 3, "Season 3", date("2016-04-24"), date("2016-06-26")), + new Season(2, 4, "Season 4", date("2017-04-23"), date("2017-06-25")), + new Season(2, 5, "Season 5", date("2018-03-25"), date("2018-05-13")) + ); + + public static final List EPISODES = Arrays.asList( + new Episode(1, 1, 1, "Yesterday's Jam", date("2006-02-03")), + new Episode(1, 1, 2, "Calamity Jen", date("2006-02-03")), + new Episode(1, 1, 3, "Fifty-Fifty", date("2006-02-10")), + new Episode(1, 1, 4, "The Red Door", date("2006-02-17")), + new Episode(1, 1, 5, "The Haunting of Bill Crouse", date("2006-02-24")), + new Episode(1, 1, 6, "Aunt Irma Visits", date("2006-03-03")), + new Episode(1, 2, 1, "The Work Outing", date("2006-08-24")), + new Episode(1, 2, 2, "Return of the Golden Child", date("2007-08-31")), + new Episode(1, 2, 3, "Moss and the German", date("2007-09-07")), + new Episode(1, 2, 4, "The Dinner Party", date("2007-09-14")), + new Episode(1, 2, 5, "Smoke and Mirrors", date("2007-09-21")), + new Episode(1, 2, 6, "Men Without Women", date("2007-09-28")), + new Episode(1, 3, 1, "From Hell", date("2008-11-21")), + new Episode(1, 3, 2, "Are We Not Men?", date("2008-11-28")), + new Episode(1, 3, 3, "Tramps Like Us", date("2008-12-05")), + new Episode(1, 3, 4, "The Speech", date("2008-12-12")), + new Episode(1, 3, 5, "Friendface", date("2008-12-19")), + new Episode(1, 3, 6, "Calendar Geeks", date("2008-12-26")), + new Episode(1, 4, 1, "Jen The Fredo", date("2010-06-25")), + new Episode(1, 4, 2, "The Final Countdown", date("2010-07-02")), + new Episode(1, 4, 3, "Something Happened", date("2010-07-09")), + new Episode(1, 4, 4, "Italian For Beginners", date("2010-07-16")), + new Episode(1, 4, 5, "Bad Boys", date("2010-07-23")), + new Episode(1, 4, 6, "Reynholm vs Reynholm", date("2010-07-30")), + new Episode(2, 1, 1, "Minimum Viable Product", date("2014-04-06")), + new Episode(2, 1, 2, "The Cap Table", date("2014-04-13")), + new Episode(2, 1, 3, "Articles of Incorporation", date("2014-04-20")), + new Episode(2, 1, 4, "Fiduciary Duties", date("2014-04-27")), + new Episode(2, 1, 5, "Signaling Risk", date("2014-05-04")), + new Episode(2, 1, 6, "Third Party Insourcing", date("2014-05-11")), + new Episode(2, 1, 7, "Proof of Concept", date("2014-05-18")), + new Episode(2, 1, 8, "Optimal Tip-to-Tip Efficiency", date("2014-06-01")), + new Episode(2, 2, 1, "Sand Hill Shuffle", date("2015-04-12")), + new Episode(2, 2, 2, "Runaway Devaluation", date("2015-04-19")), + new Episode(2, 2, 3, "Bad Money", date("2015-04-26")), + new Episode(2, 2, 4, "The Lady", date("2015-05-03")), + new Episode(2, 2, 5, "Server Space", date("2015-05-10")), + new Episode(2, 2, 6, "Homicide", date("2015-05-17")), + new Episode(2, 2, 7, "Adult Content", date("2015-05-24")), + new Episode(2, 2, 8, "White Hat/Black Hat", date("2015-05-31")), + new Episode(2, 2, 9, "Binding Arbitration", date("2015-06-07")), + new Episode(2, 2, 10, "Two Days of the Condor", date("2015-06-14")), + new Episode(2, 3, 1, "Founder Friendly", date("2016-04-24")), + new Episode(2, 3, 2, "Two in the Box", date("2016-05-01")), + new Episode(2, 3, 3, "Meinertzhagen's Haversack", date("2016-05-08")), + new Episode(2, 3, 4, "Maleant Data Systems Solutions", date("2016-05-15")), + new Episode(2, 3, 5, "The Empty Chair", date("2016-05-22")), + new Episode(2, 3, 6, "Bachmanity Insanity", date("2016-05-29")), + new Episode(2, 3, 7, "To Build a Better Beta", date("2016-06-05")), + new Episode(2, 3, 8, "Bachman's Earnings Over-Ride", date("2016-06-12")), + new Episode(2, 3, 9, "Daily Active Users", date("2016-06-19")), + new Episode(2, 3, 10, "The Uptick", date("2016-06-26")), + new Episode(2, 4, 1, "Success Failure", date("2017-04-23")), + new Episode(2, 4, 2, "Terms of Service", date("2017-04-30")), + new Episode(2, 4, 3, "Intellectual Property", date("2017-05-07")), + new Episode(2, 4, 4, "Teambuilding Exercise", date("2017-05-14")), + new Episode(2, 4, 5, "The Blood Boy", date("2017-05-21")), + new Episode(2, 4, 6, "Customer Service", date("2017-05-28")), + new Episode(2, 4, 7, "The Patent Troll", date("2017-06-04")), + new Episode(2, 4, 8, "The Keenan Vortex", date("2017-06-11")), + new Episode(2, 4, 9, "Hooli-Con", date("2017-06-18")), + new Episode(2, 4, 10, "Server Error", date("2017-06-25")), + new Episode(2, 5, 1, "Grow Fast or Die Slow", date("2018-03-25")), + new Episode(2, 5, 2, "Reorientation", date("2018-04-01")), + new Episode(2, 5, 3, "Chief Operating Officer", date("2018-04-08")), + new Episode(2, 5, 4, "Tech Evangelist", date("2018-04-15")), + new Episode(2, 5, 5, "Facial Recognition", date("2018-04-22")), + new Episode(2, 5, 6, "Artificial Emotional Intelligence", date("2018-04-29")), + new Episode(2, 5, 7, "Initial Coin Offering", date("2018-05-06")), + new Episode(2, 5, 8, "Fifty-One Percent", date("2018-05-13")) + ); + + private SeriesData() { } + + private static Instant date(String str) { + return Instant.parse(str + "T00:00:00Z"); + } +} diff --git a/query-example/src/main/java/tech/ydb/example/model/Episode.java b/query-example/src/main/java/tech/ydb/example/model/Episode.java new file mode 100644 index 0000000..0c68ef7 --- /dev/null +++ b/query-example/src/main/java/tech/ydb/example/model/Episode.java @@ -0,0 +1,40 @@ +package tech.ydb.example.model; + +import java.time.Instant; + + +public class Episode { + private final long seriesID; + private final long seasonID; + private final long episodeID; + private final String title; + private final Instant airDate; + + public Episode(long seriesID, long seasonID, long episodeID, String title, Instant airDate) { + this.seriesID = seriesID; + this.seasonID = seasonID; + this.episodeID = episodeID; + this.title = title; + this.airDate = airDate; + } + + public long seriesID() { + return seriesID; + } + + public long seasonID() { + return seasonID; + } + + public long episodeID() { + return episodeID; + } + + public String title() { + return title; + } + + public Instant airDate() { + return airDate; + } +} diff --git a/query-example/src/main/java/tech/ydb/example/model/Season.java b/query-example/src/main/java/tech/ydb/example/model/Season.java new file mode 100644 index 0000000..eeb512d --- /dev/null +++ b/query-example/src/main/java/tech/ydb/example/model/Season.java @@ -0,0 +1,40 @@ +package tech.ydb.example.model; + +import java.time.Instant; + + +public class Season { + private final long seriesID; + private final long seasonID; + private final String title; + private final Instant firstAired; + private final Instant lastAired; + + public Season(long seriesID, long seasonID, String title, Instant firstAired, Instant lastAired) { + this.seriesID = seriesID; + this.seasonID = seasonID; + this.title = title; + this.firstAired = firstAired; + this.lastAired = lastAired; + } + + public long seriesID() { + return this.seriesID; + } + + public long seasonID() { + return this.seasonID; + } + + public String title() { + return this.title; + } + + public Instant firstAired() { + return this.firstAired; + } + + public Instant lastAired() { + return this.lastAired; + } +} diff --git a/query-example/src/main/java/tech/ydb/example/model/Series.java b/query-example/src/main/java/tech/ydb/example/model/Series.java new file mode 100644 index 0000000..d074c28 --- /dev/null +++ b/query-example/src/main/java/tech/ydb/example/model/Series.java @@ -0,0 +1,34 @@ +package tech.ydb.example.model; + +import java.time.Instant; + + +public class Series { + private final long seriesID; + private final String title; + private final Instant releaseDate; + private final String seriesInfo; + + public Series(long seriesID, String title, Instant releaseDate, String seriesInfo) { + this.seriesID = seriesID; + this.title = title; + this.releaseDate = releaseDate; + this.seriesInfo = seriesInfo; + } + + public long seriesID() { + return seriesID; + } + + public String title() { + return title; + } + + public Instant releaseDate() { + return releaseDate; + } + + public String seriesInfo() { + return seriesInfo; + } +} diff --git a/query-example/src/main/resources/log4j2.xml b/query-example/src/main/resources/log4j2.xml new file mode 100644 index 0000000..cdcbde9 --- /dev/null +++ b/query-example/src/main/resources/log4j2.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/query-example/src/test/java/tech/ydb/example/BasicExampleTest.java b/query-example/src/test/java/tech/ydb/example/BasicExampleTest.java new file mode 100644 index 0000000..8d162a1 --- /dev/null +++ b/query-example/src/test/java/tech/ydb/example/BasicExampleTest.java @@ -0,0 +1,30 @@ +package tech.ydb.example; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import tech.ydb.test.junit5.YdbHelperExtension; + +/** + * + * @author Aleksandr Gorshenin + */ +public class BasicExampleTest { + @RegisterExtension + private static final YdbHelperExtension ydb = new YdbHelperExtension(); + + private static String connectionString() { + StringBuilder sb = new StringBuilder(); + sb.append(ydb.useTls() ? "grpcs://" : "grpc://" ); + sb.append(ydb.endpoint()); + sb.append(ydb.database()); + return sb.toString(); + } + + @Test + public void testBasicApp() { + App app = new App(connectionString()); + app.run(); + app.close(); + } +}