diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 31eec02..eac219f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,19 +6,34 @@ on: jobs: unit_tests: name: Run NDC tests - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout (GitHub) uses: actions/checkout@v3 with: path: cosmos - - name: Log in to GitHub Container Registry 📦 - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + - name: Set up Docker + uses: docker-practice/actions-setup-docker@master + + - name: Pull and run Azure Cosmos DB Emulator + run: | + docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator + docker run -d --name=cosmos-emulator -p 8081:8081 -p 10251:10251 -p 10252:10252 -p 10253:10253 -p 10254:10254 \ + -e AZURE_COSMOS_EMULATOR_PARTITION_COUNT=10 \ + -e AZURE_COSMOS_EMULATOR_ENABLE_DATA_PERSISTENCE=false \ + mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator + + - name: Wait for Cosmos DB Emulator to be ready + run: | + timeout 300 bash -c 'until curl -ks https://localhost:8081/_explorer/emulator.pem > /dev/null; do sleep 5; done' + echo "Cosmos DB Emulator is ready" + + - name: Download Cosmos DB Emulator certificate + run: | + curl -k https://localhost:8081/_explorer/emulator.pem > emulatorcert.crt + sudo cp emulatorcert.crt /usr/local/share/ca-certificates/ + sudo update-ca-certificates - name: Build connector run: | @@ -26,36 +41,23 @@ jobs: npm install npm run build - - name: Generate the connector configuration - env: - AZURE_COSMOS_KEY: ${{ secrets.AZURE_COSMOS_KEY }} - AZURE_COSMOS_ENDPOINT: ${{ secrets.AZURE_COSMOS_ENDPOINT }} - AZURE_COSMOS_DB_NAME: ${{ secrets.AZURE_COSMOS_DB_NAME }} + - name: Download NDC Test Binary run: | - cd cosmos - chmod +x ./dist/cli/index.js - ./dist/cli/index.js update + curl -L https://github.com/hasura/ndc-spec/releases/download/v0.1.6/ndc-test-x86_64-unknown-linux-gnu -o ndc-test + chmod +x ndc-test + ./ndc-test --version # Optional: Verify the binary works + sudo mv ndc-test /usr/local/bin/ + + + - name: Verify the ndc-test binary is accessible + run: | + ndc-test -V - - name: Start connector + - name: Run tests env: - AZURE_COSMOS_KEY: ${{ secrets.AZURE_COSMOS_KEY }} - AZURE_COSMOS_ENDPOINT: ${{ secrets.AZURE_COSMOS_ENDPOINT }} - AZURE_COSMOS_DB_NAME: ${{ secrets.AZURE_COSMOS_DB_NAME }} + AZURE_COSMOS_KEY: C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw== + AZURE_COSMOS_ENDPOINT: https://localhost:8081 + AZURE_COSMOS_DB_NAME: TestNobelLaureates run: | cd cosmos - export AZURE_COSMOS_KEY=Bh3EVxRH6BsUnger4tfXkKAvUenZhVosnvNpk185PyYZ9wd4qZO1kf7Y6hvERc7EUUJUE9j8RvDNACDbsgKqLg== - export AZURE_COSMOS_ENDPOINT=https://test-azure-cosmos-one.documents.azure.com:443/ - export AZURE_COSMOS_DB_NAME=azure-cosmos-one - export HASURA_CONFIGURATION_DIRECTORY="." - npm run start serve -- --configuration . & - - - name: Checkout ndc-spec - uses: actions/checkout@v3 - with: - repository: hasura/ndc-spec - path: ndc-spec - - - name: Run ndc-test - working-directory: ndc-spec - # temporary-solution: the --no-validate-responses flag is used to avoid the errors from the changes in ndc-spec in [PR:141](https://github.com/hasura/ndc-spec/pull/141) - run: cargo run --bin ndc-test -- replay --endpoint http://0.0.0.0:8080 --snapshots-dir ../cosmos/ndc-test-snapshots --no-validate-responses + npm run ndc-test -- --setup-emulator-data diff --git a/README.md b/README.md index 82bb7ca..6ec8fd5 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ With this connector, Hasura allows you to instantly create a real-time GraphQL A This connector is built using the [TypeScript Data Connector SDK](https://github.com/hasura/ndc-sdk-typescript) and implements the [Data Connector Spec](https://github.com/hasura/ndc-spec). -- [Connector information in the Hasura Hub](https://hasura.io/connectors/azure-cosmos) +- [See the listing in the Hasura Hub](https://hasura.io/connectors/azure-cosmos) - [Hasura V3 Documentation](https://hasura.io/docs/3.0) ## Features @@ -17,129 +17,84 @@ This connector is built using the [TypeScript Data Connector SDK](https://github Below, you'll find a matrix of all supported features for the Azure Cosmos DB for NoSQL connector: | Feature | Supported | Notes | -| ------------------------------- | --------- | ----- | -| Native Queries + Logical Models | ✅ | | -| Simple Object Query | ✅ | | -| Filter / Search | ✅ | | -| Simple Aggregation | ✅ | | -| Sort | ✅ | | -| Paginate | ✅ | | -| Nested Objects | ✅ | | -| Nested Arrays | ✅ | | -| Nested Filtering | ❌ | | -| Nested Sorting | ❌ | | -| Nested Relationships | ❌ | | +|---------------------------------|-----------|-------| +| Native Queries + Logical Models | ✅ | | +| Simple Object Query | ✅ | | +| Filter / Search | ✅ | | +| Simple Aggregation | ✅ | | +| Sort | ✅ | | +| Paginate | ✅ | | +| Nested Objects | ✅ | | +| Nested Arrays | ✅ | | +| Nested Filtering | ❌ | | +| Nested Sorting | ❌ | | +| Nested Relationships | ❌ | | ## Before you get Started 1. Create a [Hasura Cloud account](https://console.hasura.io) -2. Install the [CLI](https://hasura.io/docs/3.0/cli/installation/) -3. Install the [Hasura VS Code extension](https://marketplace.visualstudio.com/items?itemName=HasuraHQ.hasura) -4. [Create a supergraph](https://hasura.io/docs/3.0/getting-started/init-supergraph) -5. [Create a subgraph](https://hasura.io/docs/3.0/getting-started/init-subgraph) +2. Please ensure you have the [DDN CLI](https://hasura.io/docs/3.0/cli/installation) and [Docker](https://docs.docker.com/engine/install/) installed +2. [Create a supergraph](https://hasura.io/docs/3.0/getting-started/init-supergraph) +3. [Create a subgraph](https://hasura.io/docs/3.0/getting-started/init-subgraph) -## Using the connector -To use the Azure Cosmos DB for NoSQL connector, follow these steps in a Hasura project: -(Note: for more information on the following steps, please refer to the Postgres connector documentation [here](https://hasura.io/docs/3.0/getting-started/connect-to-data/connect-a-source)) +The steps below explain how to Initialize and configure a connector for local development. You can learn how to deploy a +connector — after it's been configured — [here](https://hasura.io/docs/3.0/getting-started/deployment/deploy-a-connector). +## Using the Azure Cosmos DB for NoSQL connector -### 1. Init the connector -(Note: here and following we are naming the subgraph "my_subgraph" and the connector "my_azure_cosmos") +### Step 1: Authenticate your CLI session - ```bash - ddn connector init my_azure_cosmos --subgraph my_subgraph/subgraph.yaml --hub-connector hasura/azure-cosmos --configure-port 8081 --add-to-compose-file compose.yaml - ``` - -### 2. Add your Azure Cosmos DB for NoSQL credentials - -Add you credentials to `my_subgraph/connector/my_azure_cosmos/.env.local` - -```env title="my_subgraph/connector/my_azure_cosmos/.env.local" -OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://local.hasura.dev:4317 -OTEL_SERVICE_NAME=my_subgraph_my_azure_cosmos -AZURE_COSMOS_DB_NAME= -AZURE_COSMOS_ENDPOINT= -AZURE_COSMOS_KEY= -AZURE_COSMOS_NO_OF_ROWS_TO_FETCH= +```bash +ddn auth login ``` -Note: `AZURE_COSMOS_CONNECTOR_NO_OF_ROWS_TO_FETCH` is an optional field, with 100 rows to be fetched by default. - -### 3. Introspect your Database +### Step 2: Configure the connector -From the root of your project run: +Once you have an initialized supergraph and subgraph, run the initialization command in interactive mode while +providing a name for the connector in the prompt: -```bash title="From the root of your project run:" -ddn connector introspect --connector my_subgraph/connector/my_azure_cosmos/connector.local.yaml +```bash +ddn connector init -i ``` -If you look at the `config.json` for your connector, you'll see metadata describing your Azure Cosmos DB for NoSQL mappings. +#### Step 2.1: Choose the `hasura/azure-cosmos` from the list -### 4. Restart the services +#### Step 2.2: Choose a port for the connector -Let's restart the docker compose services. Run the folowing from the root of your project: +The CLI will ask for a specific port to run the connector on. Choose a port that is not already in use or use the +default suggested port. -```bash title="From the root of your project run:" -HASURA_DDN_PAT=$(ddn auth print-pat) docker compose up --build --watch -``` - -The schema of the database can be viewed at http://localhost:8081/schema. +#### Step 2.3: Provide the env vars for the connector -### 5. Create the Hasura metadata -In a new terminal tab from your project's root directory run: +| Name | Description | Required | Default | +|----------------------------------|-------------------------------------------------------------------------------|----------|---------| +| AZURE_COSMOS_KEY | Primary/Secondary key asssociated with the Azure Cosmos DB for NoSQL | Yes | N/A | +| AZURE_COSMOS_ENDPOINT | Endpoint of the Azure Cosmos DB for NoSQL | Yes | N/A | +| AZURE_COSMOS_DB_NAME | Name of the Database | Yes | N/A | +| AZURE_COSMOS_NO_OF_ROWS_TO_FETCH | Maximum number of rows to fetch per container to infer the schema. (Optional) | No | 100 | -```bash title="Run the following from the root of your project:" -ddn connector-link add my_azure_cosmos --subgraph my_subgraph/subgraph.yaml --configure-host http://local.hasura.dev:8081 --target-env-file my_subgraph/.env.my_subgraph.local -``` -The above step will add the following env vars to the `.env.my_subgraph.local` file. -```env title="my_subgraph/.env.my_subgraph.local" -MY_SUBGRAPH_MY_AZURE_COSMOS_READ_URL=http://local.hasura.dev:8081 -MY_SUBGRAPH_MY_AZURE_COSMOS_WRITE_URL=http://local.hasura.dev:8081 -``` -The generated file has two environment variables — one for reads and one for writes. -Each key is prefixed by the subgraph name, an underscore, and the name of the -connector. +## Step 3: Introspect the connector -### 6. Update the new DataConnectorLink object -Finally, now that our `DataConnectorLink` has the correct environment variables configured for the Azure Cosmos DB for NoSQL connector, -we can run the update command to have the CLI look at the configuration JSON and transform it to reflect our database's -schema in `hml` format. From your project's root directory, run: - -```bash title="From the root of your project, run:" -ddn connector-link update my_azure_cosmos --subgraph my_subgraph/subgraph.yaml --env-file my_subgraph/.env.my_subgraph.local +```bash +ddn connector introspect ``` -After this command runs, you can open your `my_subgraph/metadata/my_azure_cosmos.hml` file and see your metadata completely -scaffolded out for you 🎉 - -### 7. Import _all_ your indices +This will generate a `configuration.json` file that will have the schema of your Azure Cosmos DB for NoSQL. -You can do this with just one command. From your project's root directory, run: +## Step 4: Add your resources -```bash title="From the root of your project, run:" -ddn connector-link update my_azure_cosmos --subgraph my_subgraph/subgraph.yaml --env-file my_subgraph/.env.my_subgraph.local --add-all-resources +```bash +ddn connector-link add-resources ``` -### 8. Create a supergraph build - -Pass the `local` subcommand along with specifying the output directory as `./engine` in the root of the project. This -directory is used by the docker-compose file to serve the engine locally. From your project's root directory, run: - -```bash title="From the root of your project, run:" -ddn supergraph build local --output-dir engine --subgraph-env-file my_subgraph:my_subgraph/.env.my_subgraph.local -``` - -You can now navigate to -[`https://console.hasura.io/local/graphql?url=http://localhost:3000`](https://console.hasura.io/local/graphql?url=http://localhost:3000) -and interact with your API using the Hasura Console. - +This command will track all the containers in your Azure Cosmos DB for NoSQL as [Models](https://hasura.io/docs/3.0/supergraph-modeling/models). ## Contributing We're happy to receive any contributions from the community. Please refer to our [development guide](./docs/development.md). diff --git a/ndc-test-snapshots/capabilities b/ndc-test-snapshots/capabilities index 902a796..ef1b052 100644 --- a/ndc-test-snapshots/capabilities +++ b/ndc-test-snapshots/capabilities @@ -1,7 +1,10 @@ { - "version": "0.1.0", + "version": "0.1.5", "capabilities": { - "query": {}, + "query": { + "nested_fields": {}, + "exists": {} + }, "mutation": {} } -} \ No newline at end of file +} diff --git a/ndc-test-snapshots/query/nobel_laureates_gte_predicate_test/expected.json b/ndc-test-snapshots/query/nobel_laureates_gte_predicate_test/expected.json index 81ab5d5..0e11ced 100644 --- a/ndc-test-snapshots/query/nobel_laureates_gte_predicate_test/expected.json +++ b/ndc-test-snapshots/query/nobel_laureates_gte_predicate_test/expected.json @@ -1,229 +1,164 @@ [ - { - "rows": [ - { - "laureates": [ - { - "id": "960", - "firstname": "Arthur", - "surname": "Ashkin", - "motivation": "\"for the optical tweezers and their application to biological systems\"", - "share": "2" - }, - { - "id": "961", - "firstname": "Gérard", - "surname": "Mourou", - "motivation": "\"for their method of generating high-intensity, ultra-short optical pulses\"", - "share": "4" - }, - { - "id": "962", - "firstname": "Donna", - "surname": "Strickland", - "motivation": "\"for their method of generating high-intensity, ultra-short optical pulses\"", - "share": "4" - } - ], - "overallMotivation": "\"for groundbreaking inventions in the field of laser physics\"", - "prize_id": 35, - "year": 2018 - }, - { - "laureates": [ - { - "id": "958", - "firstname": "James P.", - "surname": "Allison", - "motivation": "\"for their discovery of cancer therapy by inhibition of negative immune regulation\"", - "share": "2" - }, - { - "id": "959", - "firstname": "Tasuku", - "surname": "Honjo", - "motivation": "\"for their discovery of cancer therapy by inhibition of negative immune regulation\"", - "share": "2" - } - ], - "overallMotivation": null, - "prize_id": 36, - "year": 2018 - }, - { - "laureates": [ - { - "id": "944", - "firstname": "Jacques", - "surname": "Dubochet", - "motivation": "\"for developing cryo-electron microscopy for the high-resolution structure determination of biomolecules in solution\"", - "share": "3" - }, - { - "id": "945", - "firstname": "Joachim", - "surname": "Frank", - "motivation": "\"for developing cryo-electron microscopy for the high-resolution structure determination of biomolecules in solution\"", - "share": "3" - }, - { - "id": "946", - "firstname": "Richard", - "surname": "Henderson", - "motivation": "\"for developing cryo-electron microscopy for the high-resolution structure determination of biomolecules in solution\"", - "share": "3" - } - ], - "overallMotivation": null, - "prize_id": 37, - "year": 2017 - }, - { - "laureates": [ - { - "id": "949", - "firstname": "Richard H.", - "surname": "Thaler", - "motivation": "\"for his contributions to behavioural economics\"", - "share": "1" - } - ], - "overallMotivation": null, - "prize_id": 38, - "year": 2017 - }, - { - "laureates": [ - { - "id": "947", - "firstname": "Kazuo", - "surname": "Ishiguro", - "motivation": "\"who, in novels of great emotional force, has uncovered the abyss beneath our illusory sense of connection with the world\"", - "share": "1" - } - ], - "overallMotivation": null, - "prize_id": 39, - "year": 2017 - }, - { - "laureates": [ - { - "id": "948", - "motivation": "\"for its work to draw attention to the catastrophic humanitarian consequences of any use of nuclear weapons and for its ground-breaking efforts to achieve a treaty-based prohibition of such weapons\"", - "share": "1", - "firstname": "International Campaign to Abolish Nuclear Weapons" - } - ], - "overallMotivation": null, - "prize_id": 40, - "year": 2017 - }, - { - "laureates": [ - { - "id": "941", - "firstname": "Rainer", - "surname": "Weiss", - "motivation": "\"for decisive contributions to the LIGO detector and the observation of gravitational waves\"", - "share": "2" - }, - { - "id": "942", - "firstname": "Barry C.", - "surname": "Barish", - "motivation": "\"for decisive contributions to the LIGO detector and the observation of gravitational waves\"", - "share": "4" - }, - { - "id": "943", - "firstname": "Kip S.", - "surname": "Thorne", - "motivation": "\"for decisive contributions to the LIGO detector and the observation of gravitational waves\"", - "share": "4" - } - ], - "overallMotivation": null, - "prize_id": 41, - "year": 2017 - }, - { - "laureates": [ - { - "id": "938", - "firstname": "Jeffrey C.", - "surname": "Hall", - "motivation": "\"for their discoveries of molecular mechanisms controlling the circadian rhythm\"", - "share": "3" - }, - { - "id": "939", - "firstname": "Michael", - "surname": "Rosbash", - "motivation": "\"for their discoveries of molecular mechanisms controlling the circadian rhythm\"", - "share": "3" - }, - { - "id": "940", - "firstname": "Michael W.", - "surname": "Young", - "motivation": "\"for their discoveries of molecular mechanisms controlling the circadian rhythm\"", - "share": "3" - } - ], - "overallMotivation": null, - "prize_id": 42, - "year": 2017 - }, - { - "laureates": [ - { - "id": "931", - "firstname": "Jean-Pierre", - "surname": "Sauvage", - "motivation": "\"for the design and synthesis of molecular machines\"", - "share": "3" - }, - { - "id": "932", - "firstname": "Sir J. Fraser", - "surname": "Stoddart", - "motivation": "\"for the design and synthesis of molecular machines\"", - "share": "3" - }, - { - "id": "933", - "firstname": "Bernard L.", - "surname": "Feringa", - "motivation": "\"for the design and synthesis of molecular machines\"", - "share": "3" - } - ], - "overallMotivation": null, - "prize_id": 43, - "year": 2016 - }, - { - "laureates": [ - { - "id": "935", - "firstname": "Oliver", - "surname": "Hart", - "motivation": "\"for their contributions to contract theory\"", - "share": "2" - }, - { - "id": "936", - "firstname": "Bengt", - "surname": "Holmström", - "motivation": "\"for their contributions to contract theory\"", - "share": "2" - } - ], - "overallMotivation": null, - "prize_id": 44, - "year": 2016 - } - ] - } -] \ No newline at end of file + { + "rows": [ + { + "laureates": [ + { + "firstName": "Arthur", + "id": "960" + }, + { + "firstName": "Gérard", + "id": "961" + }, + { + "firstName": "Donna", + "id": "962" + } + ], + "overallMotivation": "\"for groundbreaking inventions in the field of laser physics\"", + "prize_id": 35, + "year": 2018 + }, + { + "laureates": [ + { + "firstName": "James P.", + "id": "958" + }, + { + "firstName": "Tasuku", + "id": "959" + } + ], + "overallMotivation": null, + "prize_id": 36, + "year": 2018 + }, + { + "laureates": [ + { + "firstName": "Jacques", + "id": "944" + }, + { + "firstName": "Joachim", + "id": "945" + }, + { + "firstName": "Richard", + "id": "946" + } + ], + "overallMotivation": null, + "prize_id": 37, + "year": 2017 + }, + { + "laureates": [ + { + "firstName": "Richard H.", + "id": "949" + } + ], + "overallMotivation": null, + "prize_id": 38, + "year": 2017 + }, + { + "laureates": [ + { + "firstName": "Kazuo", + "id": "947" + } + ], + "overallMotivation": null, + "prize_id": 39, + "year": 2017 + }, + { + "laureates": [ + { + "firstName": "International Campaign to Abolish Nuclear Weapons", + "id": "948" + } + ], + "overallMotivation": null, + "prize_id": 40, + "year": 2017 + }, + { + "laureates": [ + { + "firstName": "Rainer", + "id": "941" + }, + { + "firstName": "Barry C.", + "id": "942" + }, + { + "firstName": "Kip S.", + "id": "943" + } + ], + "overallMotivation": null, + "prize_id": 41, + "year": 2017 + }, + { + "laureates": [ + { + "firstName": "Jeffrey C.", + "id": "938" + }, + { + "firstName": "Michael", + "id": "939" + }, + { + "firstName": "Michael W.", + "id": "940" + } + ], + "overallMotivation": null, + "prize_id": 42, + "year": 2017 + }, + { + "laureates": [ + { + "firstName": "Jean-Pierre", + "id": "931" + }, + { + "firstName": "Sir J. Fraser", + "id": "932" + }, + { + "firstName": "Bernard L.", + "id": "933" + } + ], + "overallMotivation": null, + "prize_id": 43, + "year": 2016 + }, + { + "laureates": [ + { + "firstName": "Oliver", + "id": "935" + }, + { + "firstName": "Bengt", + "id": "936" + } + ], + "overallMotivation": null, + "prize_id": 44, + "year": 2016 + } + ] + } +] diff --git a/ndc-test-snapshots/query/nobel_laureates_gte_predicate_test/request.json b/ndc-test-snapshots/query/nobel_laureates_gte_predicate_test/request.json index 4af9562..313d73e 100644 --- a/ndc-test-snapshots/query/nobel_laureates_gte_predicate_test/request.json +++ b/ndc-test-snapshots/query/nobel_laureates_gte_predicate_test/request.json @@ -5,8 +5,23 @@ "laureates": { "type": "column", "column": "laureates", - "fields": null - }, + "fields": { + "type": "array", + "fields": { + "type": "object", + "fields": { + "firstName": { + "type": "column", + "column": "firstname" + }, + "id": { + "type": "column", + "column": "id" + } + } + } + } + }, "overallMotivation": { "type": "column", "column": "overallMotivation", diff --git a/ndc-test-snapshots/query/nobel_laureates_lte_predicate_test/expected.json b/ndc-test-snapshots/query/nobel_laureates_lte_predicate_test/expected.json index 0d1f2ed..0a7c9c5 100644 --- a/ndc-test-snapshots/query/nobel_laureates_lte_predicate_test/expected.json +++ b/ndc-test-snapshots/query/nobel_laureates_lte_predicate_test/expected.json @@ -1,242 +1,172 @@ [ - { - "rows": [ - { - "laureates": [ - { - "id": "1007", - "firstname": "David", - "surname": "Card", - "motivation": "\"for his empirical contributions to labour economics\"", - "share": "2" - }, - { - "id": "1008", - "firstname": "Joshua", - "surname": "Angrist", - "motivation": "\"for their methodological contributions to the analysis of causal relationships\"", - "share": "4" - }, - { - "id": "1009", - "firstname": "Guido", - "surname": "Imbens", - "motivation": "\"for their methodological contributions to the analysis of causal relationships\"", - "share": "4" - } - ], - "overallMotivation": null, - "prize_id": 14, - "year": 2021 - }, - { - "laureates": [ - { - "id": "1002", - "firstname": "Benjamin", - "surname": "List", - "motivation": "\"for the development of asymmetric organocatalysis\"", - "share": "2" - }, - { - "id": "1003", - "firstname": "David", - "surname": "MacMillan", - "motivation": "\"for the development of asymmetric organocatalysis\"", - "share": "2" - } - ], - "overallMotivation": null, - "prize_id": 13, - "year": 2021 - }, - { - "laureates": [ - { - "id": "1011", - "firstname": "Svante", - "surname": "Pääbo", - "motivation": "\"for his discoveries concerning the genomes of extinct hominins and human evolution\"", - "share": "1" - } - ], - "overallMotivation": null, - "prize_id": 12, - "year": 2022 - }, - { - "laureates": [ - { - "id": "1012", - "firstname": "Alain", - "surname": "Aspect", - "motivation": "\"for experiments with entangled photons, establishing the violation of Bell inequalities and pioneering quantum information science\"", - "share": "3" - }, - { - "id": "1013", - "firstname": "John ", - "surname": "Clauser", - "motivation": "\"for experiments with entangled photons, establishing the violation of Bell inequalities and pioneering quantum information science\"", - "share": "3" - }, - { - "id": "1014", - "firstname": "Anton", - "surname": "Zeilinger", - "motivation": "\"for experiments with entangled photons, establishing the violation of Bell inequalities and pioneering quantum information science\"", - "share": "3" - } - ], - "overallMotivation": null, - "prize_id": 11, - "year": 2022 - }, - { - "laureates": [ - { - "id": "1018", - "firstname": "Ales", - "surname": "Bialiatski ", - "motivation": "\"The Peace Prize laureates represent civil society in their home countries. They have for many years promoted the right to criticise power and protect the fundamental rights of citizens. They have made an outstanding effort to document war crimes, human right abuses and the abuse of power. Together they demonstrate the significance of civil society for peace and democracy.\"", - "share": "3" - }, - { - "id": "1019", - "motivation": "\"The Peace Prize laureates represent civil society in their home countries. They have for many years promoted the right to criticise power and protect the fundamental rights of citizens. They have made an outstanding effort to document war crimes, human right abuses and the abuse of power. Together they demonstrate the significance of civil society for peace and democracy.\"", - "share": "3", - "firstname": "Memorial" - }, - { - "id": "1020", - "motivation": "\"The Peace Prize laureates represent civil society in their home countries. They have for many years promoted the right to criticise power and protect the fundamental rights of citizens. They have made an outstanding effort to document war crimes, human right abuses and the abuse of power. Together they demonstrate the significance of civil society for peace and democracy.\"", - "share": "3", - "firstname": "Center for Civil Liberties" - } - ], - "overallMotivation": null, - "prize_id": 10, - "year": 2022 - }, - { - "laureates": [ - { - "id": "1017", - "firstname": "Annie", - "surname": "Ernaux", - "motivation": "\"for the courage and clinical acuity with which she uncovers the roots, estrangements and collective restraints of personal memory\"", - "share": "1" - } - ], - "overallMotivation": null, - "prize_id": 9, - "year": 2022 - }, - { - "laureates": [ - { - "id": "1021", - "firstname": "Ben", - "surname": "Bernanke", - "motivation": "\"for research on banks and financial crises\"", - "share": "3" - }, - { - "id": "1022", - "firstname": "Douglas", - "surname": "Diamond", - "motivation": "\"for research on banks and financial crises\"", - "share": "3" - }, - { - "id": "1023", - "firstname": "Philip", - "surname": "Dybvig", - "motivation": "\"for research on banks and financial crises\"", - "share": "3" - } - ], - "overallMotivation": null, - "prize_id": 8, - "year": 2022 - }, - { - "laureates": [ - { - "id": "1015", - "firstname": "Carolyn", - "surname": "Bertozzi", - "motivation": "\"for the development of click chemistry and bioorthogonal chemistry\"", - "share": "3" - }, - { - "id": "1016", - "firstname": "Morten", - "surname": "Meldal", - "motivation": "\"for the development of click chemistry and bioorthogonal chemistry\"", - "share": "3" - }, - { - "id": "743", - "firstname": "Barry", - "surname": "Sharpless", - "motivation": "\"for the development of click chemistry and bioorthogonal chemistry\"", - "share": "3" - } - ], - "overallMotivation": null, - "prize_id": 7, - "year": 2022 - }, - { - "laureates": [ - { - "id": "1024", - "firstname": "Katalin", - "surname": "Karikó", - "motivation": "\"for their discoveries concerning nucleoside base modifications that enabled the development of effective mRNA vaccines against COVID-19\"", - "share": "2" - }, - { - "id": "1025", - "firstname": "Drew", - "surname": "Weissman", - "motivation": "\"for their discoveries concerning nucleoside base modifications that enabled the development of effective mRNA vaccines against COVID-19\"", - "share": "2" - } - ], - "overallMotivation": null, - "prize_id": 6, - "year": 2023 - }, - { - "laureates": [ - { - "id": "1026", - "firstname": "Pierre", - "surname": "Agostini", - "motivation": "\"for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter\"", - "share": "3" - }, - { - "id": "1027", - "firstname": "Ferenc", - "surname": "Krausz", - "motivation": "\"for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter\"", - "share": "3" - }, - { - "id": "1028", - "firstname": "Anne", - "surname": "L’Huillier", - "motivation": "\"for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter\"", - "share": "3" - } - ], - "overallMotivation": null, - "prize_id": 5, - "year": 2023 - } - ] - } -] \ No newline at end of file + { + "rows": [ + { + "laureates": [ + { + "firstName": "David", + "id": "1007" + }, + { + "firstName": "Joshua", + "id": "1008" + }, + { + "firstName": "Guido", + "id": "1009" + } + ], + "overallMotivation": null, + "prize_id": 14, + "year": 2021 + }, + { + "laureates": [ + { + "firstName": "Benjamin", + "id": "1002" + }, + { + "firstName": "David", + "id": "1003" + } + ], + "overallMotivation": null, + "prize_id": 13, + "year": 2021 + }, + { + "laureates": [ + { + "firstName": "Svante", + "id": "1011" + } + ], + "overallMotivation": null, + "prize_id": 12, + "year": 2022 + }, + { + "laureates": [ + { + "firstName": "Alain", + "id": "1012" + }, + { + "firstName": "John ", + "id": "1013" + }, + { + "firstName": "Anton", + "id": "1014" + } + ], + "overallMotivation": null, + "prize_id": 11, + "year": 2022 + }, + { + "laureates": [ + { + "firstName": "Ales", + "id": "1018" + }, + { + "firstName": "Memorial", + "id": "1019" + }, + { + "firstName": "Center for Civil Liberties", + "id": "1020" + } + ], + "overallMotivation": null, + "prize_id": 10, + "year": 2022 + }, + { + "laureates": [ + { + "firstName": "Annie", + "id": "1017" + } + ], + "overallMotivation": null, + "prize_id": 9, + "year": 2022 + }, + { + "laureates": [ + { + "firstName": "Ben", + "id": "1021" + }, + { + "firstName": "Douglas", + "id": "1022" + }, + { + "firstName": "Philip", + "id": "1023" + } + ], + "overallMotivation": null, + "prize_id": 8, + "year": 2022 + }, + { + "laureates": [ + { + "firstName": "Carolyn", + "id": "1015" + }, + { + "firstName": "Morten", + "id": "1016" + }, + { + "firstName": "Barry", + "id": "743" + } + ], + "overallMotivation": null, + "prize_id": 7, + "year": 2022 + }, + { + "laureates": [ + { + "firstName": "Katalin", + "id": "1024" + }, + { + "firstName": "Drew", + "id": "1025" + } + ], + "overallMotivation": null, + "prize_id": 6, + "year": 2023 + }, + { + "laureates": [ + { + "firstName": "Pierre", + "id": "1026" + }, + { + "firstName": "Ferenc", + "id": "1027" + }, + { + "firstName": "Anne", + "id": "1028" + } + ], + "overallMotivation": null, + "prize_id": 5, + "year": 2023 + } + ] + } +] diff --git a/ndc-test-snapshots/query/nobel_laureates_lte_predicate_test/request.json b/ndc-test-snapshots/query/nobel_laureates_lte_predicate_test/request.json index 4ab480e..5397f9e 100644 --- a/ndc-test-snapshots/query/nobel_laureates_lte_predicate_test/request.json +++ b/ndc-test-snapshots/query/nobel_laureates_lte_predicate_test/request.json @@ -5,8 +5,23 @@ "laureates": { "type": "column", "column": "laureates", - "fields": null - }, + "fields": { + "type": "array", + "fields": { + "type": "object", + "fields": { + "firstName": { + "type": "column", + "column": "firstname" + }, + "id": { + "type": "column", + "column": "id" + } + } + } + } + }, "overallMotivation": { "type": "column", "column": "overallMotivation", diff --git a/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_on_optional_field_overallmotivation/expected.json b/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_on_optional_field_overallmotivation/expected.json index d4163ec..9e69770 100644 --- a/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_on_optional_field_overallmotivation/expected.json +++ b/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_on_optional_field_overallmotivation/expected.json @@ -1,236 +1,56 @@ [ - { - "rows": [ - { - "year_0389": 2018, - "laureates_0566": [ - { - "id": "960", - "firstname": "Arthur", - "surname": "Ashkin", - "motivation": "\"for the optical tweezers and their application to biological systems\"", - "share": "2" - }, - { - "id": "961", - "firstname": "Gérard", - "surname": "Mourou", - "motivation": "\"for their method of generating high-intensity, ultra-short optical pulses\"", - "share": "4" - }, - { - "id": "962", - "firstname": "Donna", - "surname": "Strickland", - "motivation": "\"for their method of generating high-intensity, ultra-short optical pulses\"", - "share": "4" - } - ], - "overallMotivation_6702": "\"for groundbreaking inventions in the field of laser physics\"", - "prize_id_6319": 35 - }, - { - "year_0389": 2021, - "laureates_0566": [ - { - "id": "999", - "firstname": "Syukuro", - "surname": "Manabe", - "motivation": "\"for the physical modelling of Earth’s climate, quantifying variability and reliably predicting global warming\"", - "share": "4" - }, - { - "id": "1000", - "firstname": "Klaus", - "surname": "Hasselmann", - "motivation": "\"for the physical modelling of Earth’s climate, quantifying variability and reliably predicting global warming\"", - "share": "4" - }, - { - "id": "1001", - "firstname": "Giorgio", - "surname": "Parisi", - "motivation": "\"for the discovery of the interplay of disorder and fluctuations in physical systems from atomic to planetary scales\"", - "share": "2" - } - ], - "overallMotivation_6702": "\"for groundbreaking contributions to our understanding of complex physical systems\"", - "prize_id_6319": 17 - }, - { - "year_0389": 2019, - "laureates_0566": [ - { - "id": "973", - "firstname": "James", - "surname": "Peebles", - "motivation": "\"for theoretical discoveries in physical cosmology\"", - "share": "2" - }, - { - "id": "974", - "firstname": "Michel", - "surname": "Mayor", - "motivation": "\"for the discovery of an exoplanet orbiting a solar-type star\"", - "share": "4" - }, - { - "id": "975", - "firstname": "Didier", - "surname": "Queloz", - "motivation": "\"for the discovery of an exoplanet orbiting a solar-type star\"", - "share": "4" - } - ], - "overallMotivation_6702": "\"for contributions to our understanding of the evolution of the universe and Earth’s place in the cosmos\"", - "prize_id_6319": 29 - }, - { - "year_0389": 2007, - "laureates_0566": [ - { - "id": "818", - "motivation": "\"for their efforts to build up and disseminate greater knowledge about man-made climate change, and to lay the foundations for the measures that are needed to counteract such change\"", - "share": "2", - "firstname": "Intergovernmental Panel on Climate Change" - }, - { - "id": "819", - "firstname": "Al", - "surname": "Gore", - "motivation": "\"for their efforts to build up and disseminate greater knowledge about man-made climate change, and to lay the foundations for the measures that are needed to counteract such change\"", - "share": "2" - } - ], - "overallMotivation_6702": null, - "prize_id_6319": 100 - }, - { - "year_0389": 2007, - "laureates_0566": [ - { - "id": "817", - "firstname": "Doris", - "surname": "Lessing", - "motivation": "\"that epicist of the female experience, who with scepticism, fire and visionary power has subjected a divided civilisation to scrutiny\"", - "share": "1" - } - ], - "overallMotivation_6702": null, - "prize_id_6319": 99 - }, - { - "year_0389": 2007, - "laureates_0566": [ - { - "id": "820", - "firstname": "Leonid", - "surname": "Hurwicz", - "motivation": "\"for having laid the foundations of mechanism design theory\"", - "share": "3" - }, - { - "id": "821", - "firstname": "Eric S.", - "surname": "Maskin", - "motivation": "\"for having laid the foundations of mechanism design theory\"", - "share": "3" - }, - { - "id": "822", - "firstname": "Roger B.", - "surname": "Myerson", - "motivation": "\"for having laid the foundations of mechanism design theory\"", - "share": "3" - } - ], - "overallMotivation_6702": null, - "prize_id_6319": 98 - }, - { - "year_0389": 2007, - "laureates_0566": [ - { - "id": "816", - "firstname": "Gerhard", - "surname": "Ertl", - "motivation": "\"for his studies of chemical processes on solid surfaces\"", - "share": "1" - } - ], - "overallMotivation_6702": null, - "prize_id_6319": 97 - }, - { - "year_0389": 2008, - "laureates_0566": [ - { - "id": "823", - "firstname": "Harald", - "surname": "zur Hausen", - "motivation": "\"for his discovery of human papilloma viruses causing cervical cancer\"", - "share": "2" - }, - { - "id": "824", - "firstname": "Françoise", - "surname": "Barré-Sinoussi", - "motivation": "\"for their discovery of human immunodeficiency virus\"", - "share": "4" - }, - { - "id": "825", - "firstname": "Luc", - "surname": "Montagnier", - "motivation": "\"for their discovery of human immunodeficiency virus\"", - "share": "4" - } - ], - "overallMotivation_6702": null, - "prize_id_6319": 96 - }, - { - "year_0389": 2008, - "laureates_0566": [ - { - "id": "826", - "firstname": "Yoichiro", - "surname": "Nambu", - "motivation": "\"for the discovery of the mechanism of spontaneous broken symmetry in subatomic physics\"", - "share": "2" - }, - { - "id": "827", - "firstname": "Makoto", - "surname": "Kobayashi", - "motivation": "\"for the discovery of the origin of the broken symmetry which predicts the existence of at least three families of quarks in nature\"", - "share": "4" - }, - { - "id": "828", - "firstname": "Toshihide", - "surname": "Maskawa", - "motivation": "\"for the discovery of the origin of the broken symmetry which predicts the existence of at least three families of quarks in nature\"", - "share": "4" - } - ], - "overallMotivation_6702": null, - "prize_id_6319": 95 - }, - { - "year_0389": 2008, - "laureates_0566": [ - { - "id": "833", - "firstname": "Martti", - "surname": "Ahtisaari", - "motivation": "\"for his important efforts, on several continents and over more than three decades, to resolve international conflicts\"", - "share": "1" - } - ], - "overallMotivation_6702": null, - "prize_id_6319": 94 - } - ] - } + { + "rows": [ + { + "year_0389": 2018, + "overallMotivation_6702": "\"for groundbreaking inventions in the field of laser physics\"", + "prize_id_6319": 35 + }, + { + "year_0389": 2021, + "overallMotivation_6702": "\"for groundbreaking contributions to our understanding of complex physical systems\"", + "prize_id_6319": 17 + }, + { + "year_0389": 2019, + "overallMotivation_6702": "\"for contributions to our understanding of the evolution of the universe and Earth’s place in the cosmos\"", + "prize_id_6319": 29 + }, + { + "year_0389": 2007, + "overallMotivation_6702": null, + "prize_id_6319": 100 + }, + { + "year_0389": 2007, + "overallMotivation_6702": null, + "prize_id_6319": 99 + }, + { + "year_0389": 2007, + "overallMotivation_6702": null, + "prize_id_6319": 98 + }, + { + "year_0389": 2007, + "overallMotivation_6702": null, + "prize_id_6319": 97 + }, + { + "year_0389": 2008, + "overallMotivation_6702": null, + "prize_id_6319": 96 + }, + { + "year_0389": 2008, + "overallMotivation_6702": null, + "prize_id_6319": 95 + }, + { + "year_0389": 2008, + "overallMotivation_6702": null, + "prize_id_6319": 94 + } + ] + } ] \ No newline at end of file diff --git a/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_on_optional_field_overallmotivation/request.json b/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_on_optional_field_overallmotivation/request.json index aec5a9c..14798a7 100644 --- a/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_on_optional_field_overallmotivation/request.json +++ b/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_on_optional_field_overallmotivation/request.json @@ -7,11 +7,6 @@ "column": "year", "fields": null }, - "laureates_0566": { - "type": "column", - "column": "laureates", - "fields": null - }, "overallMotivation_6702": { "type": "column", "column": "overallMotivation", diff --git a/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_on_year_and_prizeid_field/expected.json b/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_on_year_and_prizeid_field/expected.json index 756e797..429379c 100644 --- a/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_on_year_and_prizeid_field/expected.json +++ b/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_on_year_and_prizeid_field/expected.json @@ -1,208 +1,56 @@ [ - { - "rows": [ - { - "laureates_8802": [ - { - "id": "818", - "motivation": "\"for their efforts to build up and disseminate greater knowledge about man-made climate change, and to lay the foundations for the measures that are needed to counteract such change\"", - "share": "2", - "firstname": "Intergovernmental Panel on Climate Change" - }, - { - "id": "819", - "firstname": "Al", - "surname": "Gore", - "motivation": "\"for their efforts to build up and disseminate greater knowledge about man-made climate change, and to lay the foundations for the measures that are needed to counteract such change\"", - "share": "2" - } - ], - "overallMotivation_2578": null, - "prize_id_4986": 100, - "year_3902": 2007 - }, - { - "laureates_8802": [ - { - "id": "817", - "firstname": "Doris", - "surname": "Lessing", - "motivation": "\"that epicist of the female experience, who with scepticism, fire and visionary power has subjected a divided civilisation to scrutiny\"", - "share": "1" - } - ], - "overallMotivation_2578": null, - "prize_id_4986": 99, - "year_3902": 2007 - }, - { - "laureates_8802": [ - { - "id": "820", - "firstname": "Leonid", - "surname": "Hurwicz", - "motivation": "\"for having laid the foundations of mechanism design theory\"", - "share": "3" - }, - { - "id": "821", - "firstname": "Eric S.", - "surname": "Maskin", - "motivation": "\"for having laid the foundations of mechanism design theory\"", - "share": "3" - }, - { - "id": "822", - "firstname": "Roger B.", - "surname": "Myerson", - "motivation": "\"for having laid the foundations of mechanism design theory\"", - "share": "3" - } - ], - "overallMotivation_2578": null, - "prize_id_4986": 98, - "year_3902": 2007 - }, - { - "laureates_8802": [ - { - "id": "816", - "firstname": "Gerhard", - "surname": "Ertl", - "motivation": "\"for his studies of chemical processes on solid surfaces\"", - "share": "1" - } - ], - "overallMotivation_2578": null, - "prize_id_4986": 97, - "year_3902": 2007 - }, - { - "laureates_8802": [ - { - "id": "823", - "firstname": "Harald", - "surname": "zur Hausen", - "motivation": "\"for his discovery of human papilloma viruses causing cervical cancer\"", - "share": "2" - }, - { - "id": "824", - "firstname": "Françoise", - "surname": "Barré-Sinoussi", - "motivation": "\"for their discovery of human immunodeficiency virus\"", - "share": "4" - }, - { - "id": "825", - "firstname": "Luc", - "surname": "Montagnier", - "motivation": "\"for their discovery of human immunodeficiency virus\"", - "share": "4" - } - ], - "overallMotivation_2578": null, - "prize_id_4986": 96, - "year_3902": 2008 - }, - { - "laureates_8802": [ - { - "id": "826", - "firstname": "Yoichiro", - "surname": "Nambu", - "motivation": "\"for the discovery of the mechanism of spontaneous broken symmetry in subatomic physics\"", - "share": "2" - }, - { - "id": "827", - "firstname": "Makoto", - "surname": "Kobayashi", - "motivation": "\"for the discovery of the origin of the broken symmetry which predicts the existence of at least three families of quarks in nature\"", - "share": "4" - }, - { - "id": "828", - "firstname": "Toshihide", - "surname": "Maskawa", - "motivation": "\"for the discovery of the origin of the broken symmetry which predicts the existence of at least three families of quarks in nature\"", - "share": "4" - } - ], - "overallMotivation_2578": null, - "prize_id_4986": 95, - "year_3902": 2008 - }, - { - "laureates_8802": [ - { - "id": "833", - "firstname": "Martti", - "surname": "Ahtisaari", - "motivation": "\"for his important efforts, on several continents and over more than three decades, to resolve international conflicts\"", - "share": "1" - } - ], - "overallMotivation_2578": null, - "prize_id_4986": 94, - "year_3902": 2008 - }, - { - "laureates_8802": [ - { - "id": "832", - "firstname": "Jean-Marie Gustave", - "surname": "Le Clézio", - "motivation": "\"author of new departures, poetic adventure and sensual ecstasy, explorer of a humanity beyond and below the reigning civilization\"", - "share": "1" - } - ], - "overallMotivation_2578": null, - "prize_id_4986": 93, - "year_3902": 2008 - }, - { - "laureates_8802": [ - { - "id": "834", - "firstname": "Paul", - "surname": "Krugman", - "motivation": "\"for his analysis of trade patterns and location of economic activity\"", - "share": "1" - } - ], - "overallMotivation_2578": null, - "prize_id_4986": 92, - "year_3902": 2008 - }, - { - "laureates_8802": [ - { - "id": "829", - "firstname": "Osamu", - "surname": "Shimomura", - "motivation": "\"for the discovery and development of the green fluorescent protein, GFP\"", - "share": "3" - }, - { - "id": "830", - "firstname": "Martin", - "surname": "Chalfie", - "motivation": "\"for the discovery and development of the green fluorescent protein, GFP\"", - "share": "3" - }, - { - "id": "831", - "firstname": "Roger Y.", - "surname": "Tsien", - "motivation": "\"for the discovery and development of the green fluorescent protein, GFP\"", - "share": "3" - } - ], - "overallMotivation_2578": null, - "prize_id_4986": 91, - "year_3902": 2008 - } - ] - } + { + "rows": [ + { + "overallMotivation_2578": null, + "prize_id_4986": 100, + "year_3902": 2007 + }, + { + "overallMotivation_2578": null, + "prize_id_4986": 99, + "year_3902": 2007 + }, + { + "overallMotivation_2578": null, + "prize_id_4986": 98, + "year_3902": 2007 + }, + { + "overallMotivation_2578": null, + "prize_id_4986": 97, + "year_3902": 2007 + }, + { + "overallMotivation_2578": null, + "prize_id_4986": 96, + "year_3902": 2008 + }, + { + "overallMotivation_2578": null, + "prize_id_4986": 95, + "year_3902": 2008 + }, + { + "overallMotivation_2578": null, + "prize_id_4986": 94, + "year_3902": 2008 + }, + { + "overallMotivation_2578": null, + "prize_id_4986": 93, + "year_3902": 2008 + }, + { + "overallMotivation_2578": null, + "prize_id_4986": 92, + "year_3902": 2008 + }, + { + "overallMotivation_2578": null, + "prize_id_4986": 91, + "year_3902": 2008 + } + ] + } ] \ No newline at end of file diff --git a/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_on_year_and_prizeid_field/request.json b/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_on_year_and_prizeid_field/request.json index e2fee7e..8379f83 100644 --- a/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_on_year_and_prizeid_field/request.json +++ b/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_on_year_and_prizeid_field/request.json @@ -2,11 +2,6 @@ "collection": "TestNobelLaureates", "query": { "fields": { - "laureates_8802": { - "type": "column", - "column": "laureates", - "fields": null - }, "overallMotivation_2578": { "type": "column", "column": "overallMotivation", diff --git a/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_test_on_overallMotivation_and_prizeid/expected.json b/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_test_on_overallMotivation_and_prizeid/expected.json deleted file mode 100644 index d6b20cc..0000000 --- a/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_test_on_overallMotivation_and_prizeid/expected.json +++ /dev/null @@ -1,208 +0,0 @@ -[ - { - "rows": [ - { - "laureates_7252": [ - { - "id": "818", - "motivation": "\"for their efforts to build up and disseminate greater knowledge about man-made climate change, and to lay the foundations for the measures that are needed to counteract such change\"", - "share": "2", - "firstname": "Intergovernmental Panel on Climate Change" - }, - { - "id": "819", - "firstname": "Al", - "surname": "Gore", - "motivation": "\"for their efforts to build up and disseminate greater knowledge about man-made climate change, and to lay the foundations for the measures that are needed to counteract such change\"", - "share": "2" - } - ], - "overallMotivation_6623": null, - "prize_id_2142": 100, - "year_2602": 2007 - }, - { - "laureates_7252": [ - { - "id": "817", - "firstname": "Doris", - "surname": "Lessing", - "motivation": "\"that epicist of the female experience, who with scepticism, fire and visionary power has subjected a divided civilisation to scrutiny\"", - "share": "1" - } - ], - "overallMotivation_6623": null, - "prize_id_2142": 99, - "year_2602": 2007 - }, - { - "laureates_7252": [ - { - "id": "820", - "firstname": "Leonid", - "surname": "Hurwicz", - "motivation": "\"for having laid the foundations of mechanism design theory\"", - "share": "3" - }, - { - "id": "821", - "firstname": "Eric S.", - "surname": "Maskin", - "motivation": "\"for having laid the foundations of mechanism design theory\"", - "share": "3" - }, - { - "id": "822", - "firstname": "Roger B.", - "surname": "Myerson", - "motivation": "\"for having laid the foundations of mechanism design theory\"", - "share": "3" - } - ], - "overallMotivation_6623": null, - "prize_id_2142": 98, - "year_2602": 2007 - }, - { - "laureates_7252": [ - { - "id": "816", - "firstname": "Gerhard", - "surname": "Ertl", - "motivation": "\"for his studies of chemical processes on solid surfaces\"", - "share": "1" - } - ], - "overallMotivation_6623": null, - "prize_id_2142": 97, - "year_2602": 2007 - }, - { - "laureates_7252": [ - { - "id": "823", - "firstname": "Harald", - "surname": "zur Hausen", - "motivation": "\"for his discovery of human papilloma viruses causing cervical cancer\"", - "share": "2" - }, - { - "id": "824", - "firstname": "Françoise", - "surname": "Barré-Sinoussi", - "motivation": "\"for their discovery of human immunodeficiency virus\"", - "share": "4" - }, - { - "id": "825", - "firstname": "Luc", - "surname": "Montagnier", - "motivation": "\"for their discovery of human immunodeficiency virus\"", - "share": "4" - } - ], - "overallMotivation_6623": null, - "prize_id_2142": 96, - "year_2602": 2008 - }, - { - "laureates_7252": [ - { - "id": "826", - "firstname": "Yoichiro", - "surname": "Nambu", - "motivation": "\"for the discovery of the mechanism of spontaneous broken symmetry in subatomic physics\"", - "share": "2" - }, - { - "id": "827", - "firstname": "Makoto", - "surname": "Kobayashi", - "motivation": "\"for the discovery of the origin of the broken symmetry which predicts the existence of at least three families of quarks in nature\"", - "share": "4" - }, - { - "id": "828", - "firstname": "Toshihide", - "surname": "Maskawa", - "motivation": "\"for the discovery of the origin of the broken symmetry which predicts the existence of at least three families of quarks in nature\"", - "share": "4" - } - ], - "overallMotivation_6623": null, - "prize_id_2142": 95, - "year_2602": 2008 - }, - { - "laureates_7252": [ - { - "id": "833", - "firstname": "Martti", - "surname": "Ahtisaari", - "motivation": "\"for his important efforts, on several continents and over more than three decades, to resolve international conflicts\"", - "share": "1" - } - ], - "overallMotivation_6623": null, - "prize_id_2142": 94, - "year_2602": 2008 - }, - { - "laureates_7252": [ - { - "id": "832", - "firstname": "Jean-Marie Gustave", - "surname": "Le Clézio", - "motivation": "\"author of new departures, poetic adventure and sensual ecstasy, explorer of a humanity beyond and below the reigning civilization\"", - "share": "1" - } - ], - "overallMotivation_6623": null, - "prize_id_2142": 93, - "year_2602": 2008 - }, - { - "laureates_7252": [ - { - "id": "834", - "firstname": "Paul", - "surname": "Krugman", - "motivation": "\"for his analysis of trade patterns and location of economic activity\"", - "share": "1" - } - ], - "overallMotivation_6623": null, - "prize_id_2142": 92, - "year_2602": 2008 - }, - { - "laureates_7252": [ - { - "id": "829", - "firstname": "Osamu", - "surname": "Shimomura", - "motivation": "\"for the discovery and development of the green fluorescent protein, GFP\"", - "share": "3" - }, - { - "id": "830", - "firstname": "Martin", - "surname": "Chalfie", - "motivation": "\"for the discovery and development of the green fluorescent protein, GFP\"", - "share": "3" - }, - { - "id": "831", - "firstname": "Roger Y.", - "surname": "Tsien", - "motivation": "\"for the discovery and development of the green fluorescent protein, GFP\"", - "share": "3" - } - ], - "overallMotivation_6623": null, - "prize_id_2142": 91, - "year_2602": 2008 - } - ] - } -] \ No newline at end of file diff --git a/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_test_on_overallMotivation_and_prizeid/request.json b/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_test_on_overallMotivation_and_prizeid/request.json deleted file mode 100644 index 4acfa6e..0000000 --- a/ndc-test-snapshots/query/nobel_laureates_multiple_orderby_test_on_overallMotivation_and_prizeid/request.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "collection": "TestNobelLaureates", - "query": { - "fields": { - "laureates_7252": { - "type": "column", - "column": "laureates", - "fields": null - }, - "overallMotivation_6623": { - "type": "column", - "column": "overallMotivation", - "fields": null - }, - "prize_id_2142": { - "type": "column", - "column": "prize_id", - "fields": null - }, - "year_2602": { - "type": "column", - "column": "year", - "fields": null - } - }, - "limit": 10, - "order_by": { - "elements": [ - { - "order_direction": "asc", - "target": { - "type": "column", - "name": "overallMotivation", - "path": [] - } - }, - { - "order_direction": "desc", - "target": { - "type": "column", - "name": "prize_id", - "path": [] - } - } - ] - } - }, - "arguments": {}, - "collection_relationships": {} -} \ No newline at end of file diff --git a/ndc-test-snapshots/query/nobel_laureates_nested_array_field_selection/expected.json b/ndc-test-snapshots/query/nobel_laureates_nested_array_field_selection/expected.json index f31ac17..820d474 100644 --- a/ndc-test-snapshots/query/nobel_laureates_nested_array_field_selection/expected.json +++ b/ndc-test-snapshots/query/nobel_laureates_nested_array_field_selection/expected.json @@ -1,134 +1,132 @@ [ - { - "rows": [ - { - "laureates": [ - { - "firstName": "James P.", - "id": "958" - }, - { - "firstName": "Tasuku", - "id": "959" - } - ] - }, - { - "laureates": [ - { - "firstName": "Oliver", - "id": "935" - }, - { - "firstName": "Bengt", - "id": "936" - } - ] - }, - { - "laureates": [ - { - "firstName": "David J.", - "id": "928" - }, - { - "firstName": "F. Duncan M.", - "id": "929" - }, - { - "firstName": "J. Michael", - "id": "930" - } - ] - }, - { - "laureates": [ - { - "firstName": "Arthur", - "id": "960" - }, - { - "firstName": "Gérard", - "id": "961" - }, - { - "firstName": "Donna", - "id": "962" - } - ] - }, - { - "laureates": [ - { - "firstName": "Katalin", - "id": "1024" - }, - { - "firstName": "Drew", - "id": "1025" - } - ] - }, - { - "laureates": [ - { - "firstName": "Abiy", - "id": "981" - } - ] - }, - { - "laureates": [ - { - "firstName": "Serge", - "id": "876" - }, - { - "firstName": "David J.", - "id": "877" - } - ] - }, - { - "laureates": [ - { - "firstName": "Intergovernmental Panel on Climate Change", - "id": "818" - }, - { - "firstName": "Al", - "id": "819" - } - ] - }, - { - "laureates": [ - { - "firstName": "François", - "id": "887" - }, - { - "firstName": "Peter", - "id": "888" - } - ] - }, - { - "laureates": [ - { - "firstName": "Bruce A.", - "id": "861" - }, - { - "firstName": "Jules A.", - "id": "862" - }, - { - "firstName": "Ralph M.", - "id": "863" - } - ] - } + { + "rows": [ + { + "year": 2023, + "laureates": [ + { + "firstName": "Katalin", + "id": "1024" + }, + { + "firstName": "Drew", + "id": "1025" + } ] - } + }, + { + "year": 2023, + "laureates": [ + { + "firstName": "Pierre", + "id": "1026" + }, + { + "firstName": "Ferenc", + "id": "1027" + }, + { + "firstName": "Anne", + "id": "1028" + } + ] + }, + { + "year": 2023, + "laureates": [ + { + "firstName": "Narges", + "id": "1033" + } + ] + }, + { + "year": 2023, + "laureates": [ + { + "firstName": "Jon", + "id": "1032" + } + ] + }, + { + "year": 2023, + "laureates": [ + { + "firstName": "Claudia", + "id": "1034" + } + ] + }, + { + "year": 2023, + "laureates": [ + { + "firstName": "Moungi", + "id": "1029" + }, + { + "firstName": "Louis", + "id": "1030" + }, + { + "firstName": "Aleksey", + "id": "1031" + } + ] + }, + { + "year": 2022, + "laureates": [ + { + "firstName": "Svante", + "id": "1011" + } + ] + }, + { + "year": 2022, + "laureates": [ + { + "firstName": "Alain", + "id": "1012" + }, + { + "firstName": "John ", + "id": "1013" + }, + { + "firstName": "Anton", + "id": "1014" + } + ] + }, + { + "year": 2022, + "laureates": [ + { + "firstName": "Ales", + "id": "1018" + }, + { + "firstName": "Memorial", + "id": "1019" + }, + { + "firstName": "Center for Civil Liberties", + "id": "1020" + } + ] + }, + { + "year": 2022, + "laureates": [ + { + "firstName": "Annie", + "id": "1017" + } + ] + } + ] + } ] diff --git a/ndc-test-snapshots/query/nobel_laureates_nested_array_field_selection/request.json b/ndc-test-snapshots/query/nobel_laureates_nested_array_field_selection/request.json index 5c8cdf7..1499af7 100644 --- a/ndc-test-snapshots/query/nobel_laureates_nested_array_field_selection/request.json +++ b/ndc-test-snapshots/query/nobel_laureates_nested_array_field_selection/request.json @@ -2,6 +2,10 @@ "collection": "TestNobelLaureates", "query": { "fields": { + "year": { + "type": "column", + "column": "year" + }, "laureates": { "type": "column", "column": "laureates", @@ -30,7 +34,7 @@ "order_direction": "desc", "target": { "type": "column", - "name": "id", + "name": "year", "path": [] } } diff --git a/ndc-test-snapshots/query/nobel_laureates_predicate_nested_array_object_array_object_field_filtering/expected.json b/ndc-test-snapshots/query/nobel_laureates_predicate_nested_array_object_array_object_field_filtering/expected.json new file mode 100644 index 0000000..e921d27 --- /dev/null +++ b/ndc-test-snapshots/query/nobel_laureates_predicate_nested_array_object_array_object_field_filtering/expected.json @@ -0,0 +1,484 @@ +[ + { + "rows": [ + { + "laureates": [ + { + "firstName": "Leonid", + "id": "820", + "share": "3", + "awards": [ + { + "name": "Lasker Award", + "year": 2008 + }, + { + "name": "Wolf Prize in Physics", + "year": 2022 + } + ] + }, + { + "firstName": "Eric S.", + "id": "821", + "share": "3", + "awards": [ + { + "name": "Turing Award", + "year": 2010 + }, + { + "name": "Lasker Award", + "year": 2010 + }, + { + "name": "Nobel Prize in Chemistry", + "year": 2018 + } + ] + }, + { + "firstName": "Roger B.", + "id": "822", + "share": "3", + "awards": [ + { + "name": "Wolf Prize in Physics", + "year": 2001 + } + ] + } + ], + "overallMotivation": null, + "prize_id": 98, + "year": 2007 + }, + { + "laureates": [ + { + "firstName": "Intergovernmental Panel on Climate Change", + "id": "818", + "share": "2", + "awards": [ + { + "name": "Turing Award", + "year": 2011 + }, + { + "name": "Nobel Prize in Chemistry", + "year": 2021 + }, + { + "name": "Nobel Prize in Chemistry", + "year": 2016 + } + ] + }, + { + "firstName": "Al", + "id": "819", + "share": "2", + "awards": [ + { + "name": "Nobel Prize in Chemistry", + "year": 2012 + } + ] + } + ], + "overallMotivation": null, + "prize_id": 100, + "year": 2007 + }, + { + "laureates": [ + { + "firstName": "Osamu", + "id": "829", + "share": "3", + "awards": [ + { + "name": "Turing Award", + "year": 2010 + } + ] + }, + { + "firstName": "Martin", + "id": "830", + "share": "3", + "awards": [ + { + "name": "Lasker Award", + "year": 2009 + }, + { + "name": "Nobel Prize in Chemistry", + "year": 2023 + } + ] + }, + { + "firstName": "Roger Y.", + "id": "831", + "share": "3", + "awards": [ + { + "name": "Turing Award", + "year": 2004 + }, + { + "name": "Lasker Award", + "year": 2011 + } + ] + } + ], + "overallMotivation": null, + "prize_id": 91, + "year": 2008 + }, + { + "laureates": [ + { + "firstName": "Yoichiro", + "id": "826", + "share": "2", + "awards": [ + { + "name": "Nobel Prize in Chemistry", + "year": 2000 + }, + { + "name": "Turing Award", + "year": 2001 + } + ] + }, + { + "firstName": "Makoto", + "id": "827", + "share": "4", + "awards": [ + { + "name": "Wolf Prize in Physics", + "year": 2017 + }, + { + "name": "Fields Medal", + "year": 2006 + }, + { + "name": "Lasker Award", + "year": 2020 + } + ] + }, + { + "firstName": "Toshihide", + "id": "828", + "share": "4", + "awards": [ + { + "name": "Turing Award", + "year": 2012 + }, + { + "name": "Nobel Prize in Chemistry", + "year": 2023 + }, + { + "name": "Lasker Award", + "year": 2009 + } + ] + } + ], + "overallMotivation": null, + "prize_id": 95, + "year": 2008 + }, + { + "laureates": [ + { + "firstName": "Harald", + "id": "823", + "share": "2", + "awards": [ + { + "name": "Nobel Prize in Chemistry", + "year": 2017 + } + ] + }, + { + "firstName": "Françoise", + "id": "824", + "share": "4", + "awards": [ + { + "name": "Turing Award", + "year": 2021 + } + ] + }, + { + "firstName": "Luc", + "id": "825", + "share": "4", + "awards": [ + { + "name": "Lasker Award", + "year": 2006 + }, + { + "name": "Lasker Award", + "year": 2002 + } + ] + } + ], + "overallMotivation": null, + "prize_id": 96, + "year": 2008 + }, + { + "laureates": [ + { + "firstName": "Venkatraman", + "id": "841", + "share": "3", + "awards": [ + { + "name": "Turing Award", + "year": 2023 + }, + { + "name": "Lasker Award", + "year": 2006 + } + ] + }, + { + "firstName": "Thomas A.", + "id": "842", + "share": "3", + "awards": [ + { + "name": "Nobel Prize in Chemistry", + "year": 2010 + }, + { + "name": "Fields Medal", + "year": 2003 + }, + { + "name": "Lasker Award", + "year": 2011 + } + ] + }, + { + "firstName": "Ada E.", + "id": "843", + "share": "3", + "awards": [ + { + "name": "Lasker Award", + "year": 2001 + }, + { + "name": "Lasker Award", + "year": 2018 + }, + { + "name": "Nobel Prize in Chemistry", + "year": 2015 + } + ] + } + ], + "overallMotivation": null, + "prize_id": 85, + "year": 2009 + }, + { + "laureates": [ + { + "firstName": "Elinor", + "id": "846", + "share": "2", + "awards": [ + { + "name": "Lasker Award", + "year": 2015 + } + ] + }, + { + "firstName": "Oliver E.", + "id": "847", + "share": "2", + "awards": [ + { + "name": "Turing Award", + "year": 2020 + } + ] + } + ], + "overallMotivation": null, + "prize_id": 86, + "year": 2009 + }, + { + "laureates": [ + { + "firstName": "Charles K.", + "id": "838", + "share": "2", + "awards": [ + { + "name": "Wolf Prize in Physics", + "year": 2008 + } + ] + }, + { + "firstName": "Willard S.", + "id": "839", + "share": "4", + "awards": [ + { + "name": "Lasker Award", + "year": 2021 + }, + { + "name": "Nobel Prize in Chemistry", + "year": 2012 + } + ] + }, + { + "firstName": "George E.", + "id": "840", + "share": "4", + "awards": [ + { + "name": "Turing Award", + "year": 2021 + } + ] + } + ], + "overallMotivation": null, + "prize_id": 89, + "year": 2009 + }, + { + "laureates": [ + { + "firstName": "Elizabeth H.", + "id": "835", + "share": "3", + "awards": [ + { + "name": "Nobel Prize in Chemistry", + "year": 2016 + }, + { + "name": "Wolf Prize in Physics", + "year": 2004 + } + ] + }, + { + "firstName": "Carol W.", + "id": "836", + "share": "3", + "awards": [ + { + "name": "Nobel Prize in Chemistry", + "year": 2002 + }, + { + "name": "Lasker Award", + "year": 2019 + } + ] + }, + { + "firstName": "Jack W.", + "id": "837", + "share": "3", + "awards": [ + { + "name": "Wolf Prize in Physics", + "year": 2015 + }, + { + "name": "Nobel Prize in Chemistry", + "year": 2023 + }, + { + "name": "Nobel Prize in Chemistry", + "year": 2014 + } + ] + } + ], + "overallMotivation": null, + "prize_id": 90, + "year": 2009 + }, + { + "laureates": [ + { + "firstName": "Richard F.", + "id": "851", + "share": "3", + "awards": [ + { + "name": "Wolf Prize in Physics", + "year": 2004 + } + ] + }, + { + "firstName": "Ei-ichi", + "id": "852", + "share": "3", + "awards": [ + { + "name": "Lasker Award", + "year": 2003 + } + ] + }, + { + "firstName": "Akira", + "id": "853", + "share": "3", + "awards": [ + { + "name": "Turing Award", + "year": 2020 + }, + { + "name": "Nobel Prize in Chemistry", + "year": 2001 + }, + { + "name": "Nobel Prize in Chemistry", + "year": 2021 + } + ] + } + ], + "overallMotivation": null, + "prize_id": 79, + "year": 2010 + } + ] + } +] \ No newline at end of file diff --git a/ndc-test-snapshots/query/nobel_laureates_predicate_nested_array_object_array_object_field_filtering/request.json b/ndc-test-snapshots/query/nobel_laureates_predicate_nested_array_object_array_object_field_filtering/request.json new file mode 100644 index 0000000..ba61a75 --- /dev/null +++ b/ndc-test-snapshots/query/nobel_laureates_predicate_nested_array_object_array_object_field_filtering/request.json @@ -0,0 +1,97 @@ +{ + "collection": "TestNobelLaureates", + "query": { + "fields": { + "laureates": { + "type": "column", + "column": "laureates", + "fields": { + "type": "array", + "fields": { + "type": "object", + "fields": { + "firstName": { + "type": "column", + "column": "firstname" + }, + "id": { + "type": "column", + "column": "id" + }, + "share": { + "type": "column", + "column": "share" + }, + "awards": { + "type": "column", + "column": "awards", + "fields": { + "type": "array", + "fields": { + "type": "object", + "fields": { + "name": { + "type": "column", + "column": "award_name" + }, + "year": { + "type": "column", + "column": "year" + } + } + } + } + } + } + } + } + }, + "overallMotivation": { + "type": "column", + "column": "overallMotivation", + "fields": null + }, + "prize_id": { + "type": "column", + "column": "prize_id", + "fields": null + }, + "year": { + "type": "column", + "column": "year", + "fields": null + } + }, + "limit": 10, + "predicate": { + "type": "binary_comparison_operator", + "column": { + "type": "column", + "name": "laureates", + "field_path": [ + "share" + ], + "path": [] + }, + "operator": "gt", + "value": { + "type": "scalar", + "value": "1" + } + }, + "order_by": { + "elements": [ + { + "order_direction": "asc", + "target": { + "type": "column", + "name": "year", + "path": [] + } + } + ] + } + }, + "arguments": {}, + "collection_relationships": {} +} diff --git a/ndc-test-snapshots/query/nobel_laureates_predicate_nested_array_object_field_filtering/expected.json b/ndc-test-snapshots/query/nobel_laureates_predicate_nested_array_object_field_filtering/expected.json new file mode 100644 index 0000000..ef58ac3 --- /dev/null +++ b/ndc-test-snapshots/query/nobel_laureates_predicate_nested_array_object_field_filtering/expected.json @@ -0,0 +1,216 @@ +[ + { + "rows": [ + { + "laureates": [ + { + "firstName": "Leonid", + "id": "820", + "share": "3" + }, + { + "firstName": "Eric S.", + "id": "821", + "share": "3" + }, + { + "firstName": "Roger B.", + "id": "822", + "share": "3" + } + ], + "overallMotivation": null, + "prize_id": 98, + "year": 2007 + }, + { + "laureates": [ + { + "firstName": "Intergovernmental Panel on Climate Change", + "id": "818", + "share": "2" + }, + { + "firstName": "Al", + "id": "819", + "share": "2" + } + ], + "overallMotivation": null, + "prize_id": 100, + "year": 2007 + }, + { + "laureates": [ + { + "firstName": "Osamu", + "id": "829", + "share": "3" + }, + { + "firstName": "Martin", + "id": "830", + "share": "3" + }, + { + "firstName": "Roger Y.", + "id": "831", + "share": "3" + } + ], + "overallMotivation": null, + "prize_id": 91, + "year": 2008 + }, + { + "laureates": [ + { + "firstName": "Yoichiro", + "id": "826", + "share": "2" + }, + { + "firstName": "Makoto", + "id": "827", + "share": "4" + }, + { + "firstName": "Toshihide", + "id": "828", + "share": "4" + } + ], + "overallMotivation": null, + "prize_id": 95, + "year": 2008 + }, + { + "laureates": [ + { + "firstName": "Harald", + "id": "823", + "share": "2" + }, + { + "firstName": "Françoise", + "id": "824", + "share": "4" + }, + { + "firstName": "Luc", + "id": "825", + "share": "4" + } + ], + "overallMotivation": null, + "prize_id": 96, + "year": 2008 + }, + { + "laureates": [ + { + "firstName": "Venkatraman", + "id": "841", + "share": "3" + }, + { + "firstName": "Thomas A.", + "id": "842", + "share": "3" + }, + { + "firstName": "Ada E.", + "id": "843", + "share": "3" + } + ], + "overallMotivation": null, + "prize_id": 85, + "year": 2009 + }, + { + "laureates": [ + { + "firstName": "Elinor", + "id": "846", + "share": "2" + }, + { + "firstName": "Oliver E.", + "id": "847", + "share": "2" + } + ], + "overallMotivation": null, + "prize_id": 86, + "year": 2009 + }, + { + "laureates": [ + { + "firstName": "Charles K.", + "id": "838", + "share": "2" + }, + { + "firstName": "Willard S.", + "id": "839", + "share": "4" + }, + { + "firstName": "George E.", + "id": "840", + "share": "4" + } + ], + "overallMotivation": null, + "prize_id": 89, + "year": 2009 + }, + { + "laureates": [ + { + "firstName": "Elizabeth H.", + "id": "835", + "share": "3" + }, + { + "firstName": "Carol W.", + "id": "836", + "share": "3" + }, + { + "firstName": "Jack W.", + "id": "837", + "share": "3" + } + ], + "overallMotivation": null, + "prize_id": 90, + "year": 2009 + }, + { + "laureates": [ + { + "firstName": "Richard F.", + "id": "851", + "share": "3" + }, + { + "firstName": "Ei-ichi", + "id": "852", + "share": "3" + }, + { + "firstName": "Akira", + "id": "853", + "share": "3" + } + ], + "overallMotivation": null, + "prize_id": 79, + "year": 2010 + } + ] + } +] \ No newline at end of file diff --git a/ndc-test-snapshots/query/nobel_laureates_predicate_nested_array_object_field_filtering/request.json b/ndc-test-snapshots/query/nobel_laureates_predicate_nested_array_object_field_filtering/request.json new file mode 100644 index 0000000..eb04f86 --- /dev/null +++ b/ndc-test-snapshots/query/nobel_laureates_predicate_nested_array_object_field_filtering/request.json @@ -0,0 +1,75 @@ +{ + "collection": "TestNobelLaureates", + "query": { + "fields": { + "laureates": { + "type": "column", + "column": "laureates", + "fields": { + "type": "array", + "fields": { + "type": "object", + "fields": { + "firstName": { + "type": "column", + "column": "firstname" + }, + "id": { + "type": "column", + "column": "id" + }, + "share": { + "type": "column", + "column": "share" + } + } + } + } + }, + "overallMotivation": { + "type": "column", + "column": "overallMotivation", + "fields": null + }, + "prize_id": { + "type": "column", + "column": "prize_id", + "fields": null + }, + "year": { + "type": "column", + "column": "year", + "fields": null + } + }, + "limit": 10, + "predicate": { + "type": "binary_comparison_operator", + "column": { + "type": "column", + "name": "laureates", + "field_path": ["share"], + "path": [] + }, + "operator": "gt", + "value": { + "type": "scalar", + "value": "1" + } + }, + "order_by": { + "elements": [ + { + "order_direction": "asc", + "target": { + "type": "column", + "name": "year", + "path": [] + } + } + ] + } + }, + "arguments": {}, + "collection_relationships": {} +} diff --git a/ndc-test-snapshots/query/nobel_laureates_predicate_on_category_field_test/expected.json b/ndc-test-snapshots/query/nobel_laureates_predicate_on_category_field_test/expected.json index 2c4576d..b2ad5c2 100644 --- a/ndc-test-snapshots/query/nobel_laureates_predicate_on_category_field_test/expected.json +++ b/ndc-test-snapshots/query/nobel_laureates_predicate_on_category_field_test/expected.json @@ -1,279 +1,1012 @@ [ - { - "rows": [ - { - "laureates": [ - { - "id": "1026", - "firstname": "Pierre", - "surname": "Agostini", - "motivation": "\"for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter\"", - "share": "3" - }, - { - "id": "1027", - "firstname": "Ferenc", - "surname": "Krausz", - "motivation": "\"for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter\"", - "share": "3" - }, - { - "id": "1028", - "firstname": "Anne", - "surname": "L’Huillier", - "motivation": "\"for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter\"", - "share": "3" - } - ], - "overallMotivation": null, - "prize_id": 5, - "year": 2023 - }, - { - "laureates": [ - { - "id": "1012", - "firstname": "Alain", - "surname": "Aspect", - "motivation": "\"for experiments with entangled photons, establishing the violation of Bell inequalities and pioneering quantum information science\"", - "share": "3" - }, - { - "id": "1013", - "firstname": "John ", - "surname": "Clauser", - "motivation": "\"for experiments with entangled photons, establishing the violation of Bell inequalities and pioneering quantum information science\"", - "share": "3" - }, - { - "id": "1014", - "firstname": "Anton", - "surname": "Zeilinger", - "motivation": "\"for experiments with entangled photons, establishing the violation of Bell inequalities and pioneering quantum information science\"", - "share": "3" - } - ], - "overallMotivation": null, - "prize_id": 11, - "year": 2022 - }, - { - "laureates": [ - { - "id": "999", - "firstname": "Syukuro", - "surname": "Manabe", - "motivation": "\"for the physical modelling of Earth’s climate, quantifying variability and reliably predicting global warming\"", - "share": "4" - }, - { - "id": "1000", - "firstname": "Klaus", - "surname": "Hasselmann", - "motivation": "\"for the physical modelling of Earth’s climate, quantifying variability and reliably predicting global warming\"", - "share": "4" - }, - { - "id": "1001", - "firstname": "Giorgio", - "surname": "Parisi", - "motivation": "\"for the discovery of the interplay of disorder and fluctuations in physical systems from atomic to planetary scales\"", - "share": "2" - } - ], - "overallMotivation": "\"for groundbreaking contributions to our understanding of complex physical systems\"", - "prize_id": 17, - "year": 2021 - }, - { - "laureates": [ - { - "id": "988", - "firstname": "Roger", - "surname": "Penrose", - "motivation": "\"for the discovery that black hole formation is a robust prediction of the general theory of relativity\"", - "share": "2" - }, - { - "id": "989", - "firstname": "Reinhard", - "surname": "Genzel", - "motivation": "\"for the discovery of a supermassive compact object at the centre of our galaxy\"", - "share": "4" - }, - { - "id": "990", - "firstname": "Andrea", - "surname": "Ghez", - "motivation": "\"for the discovery of a supermassive compact object at the centre of our galaxy\"", - "share": "4" - } - ], - "overallMotivation": null, - "prize_id": 23, - "year": 2020 - }, - { - "laureates": [ - { - "id": "973", - "firstname": "James", - "surname": "Peebles", - "motivation": "\"for theoretical discoveries in physical cosmology\"", - "share": "2" - }, - { - "id": "974", - "firstname": "Michel", - "surname": "Mayor", - "motivation": "\"for the discovery of an exoplanet orbiting a solar-type star\"", - "share": "4" - }, - { - "id": "975", - "firstname": "Didier", - "surname": "Queloz", - "motivation": "\"for the discovery of an exoplanet orbiting a solar-type star\"", - "share": "4" - } - ], - "overallMotivation": "\"for contributions to our understanding of the evolution of the universe and Earth’s place in the cosmos\"", - "prize_id": 29, - "year": 2019 - }, - { - "laureates": [ - { - "id": "960", - "firstname": "Arthur", - "surname": "Ashkin", - "motivation": "\"for the optical tweezers and their application to biological systems\"", - "share": "2" - }, - { - "id": "961", - "firstname": "Gérard", - "surname": "Mourou", - "motivation": "\"for their method of generating high-intensity, ultra-short optical pulses\"", - "share": "4" - }, - { - "id": "962", - "firstname": "Donna", - "surname": "Strickland", - "motivation": "\"for their method of generating high-intensity, ultra-short optical pulses\"", - "share": "4" - } - ], - "overallMotivation": "\"for groundbreaking inventions in the field of laser physics\"", - "prize_id": 35, - "year": 2018 - }, - { - "laureates": [ - { - "id": "941", - "firstname": "Rainer", - "surname": "Weiss", - "motivation": "\"for decisive contributions to the LIGO detector and the observation of gravitational waves\"", - "share": "2" - }, - { - "id": "942", - "firstname": "Barry C.", - "surname": "Barish", - "motivation": "\"for decisive contributions to the LIGO detector and the observation of gravitational waves\"", - "share": "4" - }, - { - "id": "943", - "firstname": "Kip S.", - "surname": "Thorne", - "motivation": "\"for decisive contributions to the LIGO detector and the observation of gravitational waves\"", - "share": "4" - } - ], - "overallMotivation": null, - "prize_id": 41, - "year": 2017 - }, - { - "laureates": [ - { - "id": "928", - "firstname": "David J.", - "surname": "Thouless", - "motivation": "\"for theoretical discoveries of topological phase transitions and topological phases of matter\"", - "share": "2" - }, - { - "id": "929", - "firstname": "F. Duncan M.", - "surname": "Haldane", - "motivation": "\"for theoretical discoveries of topological phase transitions and topological phases of matter\"", - "share": "4" - }, - { - "id": "930", - "firstname": "J. Michael", - "surname": "Kosterlitz", - "motivation": "\"for theoretical discoveries of topological phase transitions and topological phases of matter\"", - "share": "4" - } - ], - "overallMotivation": null, - "prize_id": 47, - "year": 2016 - }, - { - "laureates": [ - { - "id": "919", - "firstname": "Takaaki", - "surname": "Kajita", - "motivation": "\"for the discovery of neutrino oscillations, which shows that neutrinos have mass\"", - "share": "2" - }, - { - "id": "920", - "firstname": "Arthur B.", - "surname": "McDonald", - "motivation": "\"for the discovery of neutrino oscillations, which shows that neutrinos have mass\"", - "share": "2" - } - ], - "overallMotivation": null, - "prize_id": 53, - "year": 2015 - }, - { - "laureates": [ - { - "id": "906", - "firstname": "Isamu", - "surname": "Akasaki", - "motivation": "\"for the invention of efficient blue light-emitting diodes which has enabled bright and energy-saving white light sources\"", - "share": "3" - }, - { - "id": "907", - "firstname": "Hiroshi", - "surname": "Amano", - "motivation": "\"for the invention of efficient blue light-emitting diodes which has enabled bright and energy-saving white light sources\"", - "share": "3" - }, - { - "id": "908", - "firstname": "Shuji", - "surname": "Nakamura", - "motivation": "\"for the invention of efficient blue light-emitting diodes which has enabled bright and energy-saving white light sources\"", - "share": "3" - } - ], - "overallMotivation": null, - "prize_id": 59, - "year": 2014 - } - ] - } -] \ No newline at end of file + { + "rows": [ + { + "laureates": [ + { + "id": "1026", + "firstname": "Pierre", + "surname": "Agostini", + "motivation": "\"for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter\"", + "share": "3", + "birth": { + "year": 1976, + "country": { + "city": "Los Angeles", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2003, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Fields Medal", + "year": 2007, + "details": { + "category": "computer science", + "organization": "Nobel Committee" + } + } + ] + }, + { + "id": "1027", + "firstname": "Ferenc", + "surname": "Krausz", + "motivation": "\"for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter\"", + "share": "3", + "birth": { + "year": 1955, + "country": { + "city": "Berlin", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2016, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Turing Award", + "year": 2014, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2006, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + } + ] + }, + { + "id": "1028", + "firstname": "Anne", + "surname": "L’Huillier", + "motivation": "\"for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter\"", + "share": "3", + "birth": { + "year": 1966, + "country": { + "city": "Los Angeles", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2023, + "details": { + "category": "computer science", + "organization": "Nobel Committee" + } + } + ] + } + ], + "overallMotivation": null, + "prize_id": 5, + "year": 2023 + }, + { + "laureates": [ + { + "id": "1012", + "firstname": "Alain", + "surname": "Aspect", + "motivation": "\"for experiments with entangled photons, establishing the violation of Bell inequalities and pioneering quantum information science\"", + "share": "3", + "birth": { + "year": 1981, + "country": { + "city": "London", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2022, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2016, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2001, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + } + ] + }, + { + "id": "1013", + "firstname": "John ", + "surname": "Clauser", + "motivation": "\"for experiments with entangled photons, establishing the violation of Bell inequalities and pioneering quantum information science\"", + "share": "3", + "birth": { + "year": 2013, + "country": { + "city": "Sydney", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2000, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2006, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2006, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + } + ] + }, + { + "id": "1014", + "firstname": "Anton", + "surname": "Zeilinger", + "motivation": "\"for experiments with entangled photons, establishing the violation of Bell inequalities and pioneering quantum information science\"", + "share": "3", + "birth": { + "year": 1955, + "country": { + "city": "Tokyo", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2003, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] + } + ], + "overallMotivation": null, + "prize_id": 11, + "year": 2022 + }, + { + "laureates": [ + { + "id": "999", + "firstname": "Syukuro", + "surname": "Manabe", + "motivation": "\"for the physical modelling of Earth’s climate, quantifying variability and reliably predicting global warming\"", + "share": "4", + "birth": { + "year": 1986, + "country": { + "city": "New York", + "state": "Maharashtra" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2001, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2016, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + } + ] + }, + { + "id": "1000", + "firstname": "Klaus", + "surname": "Hasselmann", + "motivation": "\"for the physical modelling of Earth’s climate, quantifying variability and reliably predicting global warming\"", + "share": "4", + "birth": { + "year": 1966, + "country": { + "city": "Tokyo", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2019, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Turing Award", + "year": 2005, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + } + ] + }, + { + "id": "1001", + "firstname": "Giorgio", + "surname": "Parisi", + "motivation": "\"for the discovery of the interplay of disorder and fluctuations in physical systems from atomic to planetary scales\"", + "share": "2", + "birth": { + "year": 1956, + "country": { + "city": "Shanghai", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2010, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + } + ] + } + ], + "overallMotivation": "\"for groundbreaking contributions to our understanding of complex physical systems\"", + "prize_id": 17, + "year": 2021 + }, + { + "laureates": [ + { + "id": "988", + "firstname": "Roger", + "surname": "Penrose", + "motivation": "\"for the discovery that black hole formation is a robust prediction of the general theory of relativity\"", + "share": "2", + "birth": { + "year": 2011, + "country": { + "city": "Sao Paulo", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2001, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + } + ] + }, + { + "id": "989", + "firstname": "Reinhard", + "surname": "Genzel", + "motivation": "\"for the discovery of a supermassive compact object at the centre of our galaxy\"", + "share": "4", + "birth": { + "year": 1992, + "country": { + "city": "Tokyo", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2020, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2006, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2012, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] + }, + { + "id": "990", + "firstname": "Andrea", + "surname": "Ghez", + "motivation": "\"for the discovery of a supermassive compact object at the centre of our galaxy\"", + "share": "4", + "birth": { + "year": 2006, + "country": { + "city": "Tokyo", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2007, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2003, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2013, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] + } + ], + "overallMotivation": null, + "prize_id": 23, + "year": 2020 + }, + { + "laureates": [ + { + "id": "973", + "firstname": "James", + "surname": "Peebles", + "motivation": "\"for theoretical discoveries in physical cosmology\"", + "share": "2", + "birth": { + "year": 1974, + "country": { + "city": "Tokyo", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2023, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2005, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2009, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + } + ] + }, + { + "id": "974", + "firstname": "Michel", + "surname": "Mayor", + "motivation": "\"for the discovery of an exoplanet orbiting a solar-type star\"", + "share": "4", + "birth": { + "year": 2010, + "country": { + "city": "Shanghai", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2015, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2019, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + } + ] + }, + { + "id": "975", + "firstname": "Didier", + "surname": "Queloz", + "motivation": "\"for the discovery of an exoplanet orbiting a solar-type star\"", + "share": "4", + "birth": { + "year": 2020, + "country": { + "city": "Los Angeles", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2001, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + } + ] + } + ], + "overallMotivation": "\"for contributions to our understanding of the evolution of the universe and Earth’s place in the cosmos\"", + "prize_id": 29, + "year": 2019 + }, + { + "laureates": [ + { + "id": "960", + "firstname": "Arthur", + "surname": "Ashkin", + "motivation": "\"for the optical tweezers and their application to biological systems\"", + "share": "2", + "birth": { + "year": 1973, + "country": { + "city": "Berlin", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2021, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Fields Medal", + "year": 2009, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] + }, + { + "id": "961", + "firstname": "Gérard", + "surname": "Mourou", + "motivation": "\"for their method of generating high-intensity, ultra-short optical pulses\"", + "share": "4", + "birth": { + "year": 1960, + "country": { + "city": "Los Angeles", + "state": "Maharashtra" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2006, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2001, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] + }, + { + "id": "962", + "firstname": "Donna", + "surname": "Strickland", + "motivation": "\"for their method of generating high-intensity, ultra-short optical pulses\"", + "share": "4", + "birth": { + "year": 1973, + "country": { + "city": "Sao Paulo", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2021, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] + } + ], + "overallMotivation": "\"for groundbreaking inventions in the field of laser physics\"", + "prize_id": 35, + "year": 2018 + }, + { + "laureates": [ + { + "id": "941", + "firstname": "Rainer", + "surname": "Weiss", + "motivation": "\"for decisive contributions to the LIGO detector and the observation of gravitational waves\"", + "share": "2", + "birth": { + "year": 1952, + "country": { + "city": "Berlin", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2005, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2014, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + } + ] + }, + { + "id": "942", + "firstname": "Barry C.", + "surname": "Barish", + "motivation": "\"for decisive contributions to the LIGO detector and the observation of gravitational waves\"", + "share": "4", + "birth": { + "year": 1974, + "country": { + "city": "Paris", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2006, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2022, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2014, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + } + ] + }, + { + "id": "943", + "firstname": "Kip S.", + "surname": "Thorne", + "motivation": "\"for decisive contributions to the LIGO detector and the observation of gravitational waves\"", + "share": "4", + "birth": { + "year": 1975, + "country": { + "city": "Berlin", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2016, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2017, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + } + ] + } + ], + "overallMotivation": null, + "prize_id": 41, + "year": 2017 + }, + { + "laureates": [ + { + "id": "928", + "firstname": "David J.", + "surname": "Thouless", + "motivation": "\"for theoretical discoveries of topological phase transitions and topological phases of matter\"", + "share": "2", + "birth": { + "year": 1968, + "country": { + "city": "Sao Paulo", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2020, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2005, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + } + ] + }, + { + "id": "929", + "firstname": "F. Duncan M.", + "surname": "Haldane", + "motivation": "\"for theoretical discoveries of topological phase transitions and topological phases of matter\"", + "share": "4", + "birth": { + "year": 2009, + "country": { + "city": "Sydney", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2008, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2007, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + } + ] + }, + { + "id": "930", + "firstname": "J. Michael", + "surname": "Kosterlitz", + "motivation": "\"for theoretical discoveries of topological phase transitions and topological phases of matter\"", + "share": "4", + "birth": { + "year": 1967, + "country": { + "city": "Paris", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2011, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + } + ] + } + ], + "overallMotivation": null, + "prize_id": 47, + "year": 2016 + }, + { + "laureates": [ + { + "id": "919", + "firstname": "Takaaki", + "surname": "Kajita", + "motivation": "\"for the discovery of neutrino oscillations, which shows that neutrinos have mass\"", + "share": "2", + "birth": { + "year": 1992, + "country": { + "city": "Sydney", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2013, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Fields Medal", + "year": 2004, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Turing Award", + "year": 2012, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + } + ] + }, + { + "id": "920", + "firstname": "Arthur B.", + "surname": "McDonald", + "motivation": "\"for the discovery of neutrino oscillations, which shows that neutrinos have mass\"", + "share": "2", + "birth": { + "year": 1991, + "country": { + "city": "Mumbai", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2020, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2011, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2020, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + } + ] + } + ], + "overallMotivation": null, + "prize_id": 53, + "year": 2015 + }, + { + "laureates": [ + { + "id": "906", + "firstname": "Isamu", + "surname": "Akasaki", + "motivation": "\"for the invention of efficient blue light-emitting diodes which has enabled bright and energy-saving white light sources\"", + "share": "3", + "birth": { + "year": 1997, + "country": { + "city": "Berlin", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2002, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + } + ] + }, + { + "id": "907", + "firstname": "Hiroshi", + "surname": "Amano", + "motivation": "\"for the invention of efficient blue light-emitting diodes which has enabled bright and energy-saving white light sources\"", + "share": "3", + "birth": { + "year": 2009, + "country": { + "city": "Paris", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2022, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2002, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Turing Award", + "year": 2012, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + } + ] + }, + { + "id": "908", + "firstname": "Shuji", + "surname": "Nakamura", + "motivation": "\"for the invention of efficient blue light-emitting diodes which has enabled bright and energy-saving white light sources\"", + "share": "3", + "birth": { + "year": 1988, + "country": { + "city": "Mumbai", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2016, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + } + ] + } + ], + "overallMotivation": null, + "prize_id": 59, + "year": 2014 + } + ] + } +] diff --git a/ndc-test-snapshots/query/nobel_laureates_predicate_on_overallMotivation_field/expected.json b/ndc-test-snapshots/query/nobel_laureates_predicate_on_overallMotivation_field/expected.json index 17c5535..b65a1b0 100644 --- a/ndc-test-snapshots/query/nobel_laureates_predicate_on_overallMotivation_field/expected.json +++ b/ndc-test-snapshots/query/nobel_laureates_predicate_on_overallMotivation_field/expected.json @@ -1,34 +1,101 @@ [ - { - "rows": [ - { - "laureates": [ - { - "id": "960", - "firstname": "Arthur", - "surname": "Ashkin", - "motivation": "\"for the optical tweezers and their application to biological systems\"", - "share": "2" - }, - { - "id": "961", - "firstname": "Gérard", - "surname": "Mourou", - "motivation": "\"for their method of generating high-intensity, ultra-short optical pulses\"", - "share": "4" - }, - { - "id": "962", - "firstname": "Donna", - "surname": "Strickland", - "motivation": "\"for their method of generating high-intensity, ultra-short optical pulses\"", - "share": "4" - } - ], - "overallMotivation": "\"for groundbreaking inventions in the field of laser physics\"", - "prize_id": 35, - "year": 2018 - } - ] - } + { + "rows": [ + { + "laureates": [ + { + "id": "960", + "firstname": "Arthur", + "surname": "Ashkin", + "motivation": "\"for the optical tweezers and their application to biological systems\"", + "share": "2", + "birth": { + "year": 1973, + "country": { + "city": "Berlin", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2021, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Fields Medal", + "year": 2009, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] + }, + { + "id": "961", + "firstname": "Gérard", + "surname": "Mourou", + "motivation": "\"for their method of generating high-intensity, ultra-short optical pulses\"", + "share": "4", + "birth": { + "year": 1960, + "country": { + "city": "Los Angeles", + "state": "Maharashtra" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2006, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2001, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] + }, + { + "id": "962", + "firstname": "Donna", + "surname": "Strickland", + "motivation": "\"for their method of generating high-intensity, ultra-short optical pulses\"", + "share": "4", + "birth": { + "year": 1973, + "country": { + "city": "Sao Paulo", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2021, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] + } + ], + "overallMotivation": "\"for groundbreaking inventions in the field of laser physics\"", + "prize_id": 35, + "year": 2018 + } + ] + } ] \ No newline at end of file diff --git a/ndc-test-snapshots/query/nobel_laureates_predicate_on_year_orderby_test/expected.json b/ndc-test-snapshots/query/nobel_laureates_predicate_on_year_orderby_test/expected.json index d8c877a..dab48e4 100644 --- a/ndc-test-snapshots/query/nobel_laureates_predicate_on_year_orderby_test/expected.json +++ b/ndc-test-snapshots/query/nobel_laureates_predicate_on_year_orderby_test/expected.json @@ -1,131 +1,36 @@ [ - { - "rows": [ - { - "laureates": [ - { - "id": "944", - "firstname": "Jacques", - "surname": "Dubochet", - "motivation": "\"for developing cryo-electron microscopy for the high-resolution structure determination of biomolecules in solution\"", - "share": "3" - }, - { - "id": "945", - "firstname": "Joachim", - "surname": "Frank", - "motivation": "\"for developing cryo-electron microscopy for the high-resolution structure determination of biomolecules in solution\"", - "share": "3" - }, - { - "id": "946", - "firstname": "Richard", - "surname": "Henderson", - "motivation": "\"for developing cryo-electron microscopy for the high-resolution structure determination of biomolecules in solution\"", - "share": "3" - } - ], - "overallMotivation": null, - "prize_id": 37, - "year": 2017 - }, - { - "laureates": [ - { - "id": "949", - "firstname": "Richard H.", - "surname": "Thaler", - "motivation": "\"for his contributions to behavioural economics\"", - "share": "1" - } - ], - "overallMotivation": null, - "prize_id": 38, - "year": 2017 - }, - { - "laureates": [ - { - "id": "947", - "firstname": "Kazuo", - "surname": "Ishiguro", - "motivation": "\"who, in novels of great emotional force, has uncovered the abyss beneath our illusory sense of connection with the world\"", - "share": "1" - } - ], - "overallMotivation": null, - "prize_id": 39, - "year": 2017 - }, - { - "laureates": [ - { - "id": "948", - "motivation": "\"for its work to draw attention to the catastrophic humanitarian consequences of any use of nuclear weapons and for its ground-breaking efforts to achieve a treaty-based prohibition of such weapons\"", - "share": "1", - "firstname": "International Campaign to Abolish Nuclear Weapons" - } - ], - "overallMotivation": null, - "prize_id": 40, - "year": 2017 - }, - { - "laureates": [ - { - "id": "941", - "firstname": "Rainer", - "surname": "Weiss", - "motivation": "\"for decisive contributions to the LIGO detector and the observation of gravitational waves\"", - "share": "2" - }, - { - "id": "942", - "firstname": "Barry C.", - "surname": "Barish", - "motivation": "\"for decisive contributions to the LIGO detector and the observation of gravitational waves\"", - "share": "4" - }, - { - "id": "943", - "firstname": "Kip S.", - "surname": "Thorne", - "motivation": "\"for decisive contributions to the LIGO detector and the observation of gravitational waves\"", - "share": "4" - } - ], - "overallMotivation": null, - "prize_id": 41, - "year": 2017 - }, - { - "laureates": [ - { - "id": "938", - "firstname": "Jeffrey C.", - "surname": "Hall", - "motivation": "\"for their discoveries of molecular mechanisms controlling the circadian rhythm\"", - "share": "3" - }, - { - "id": "939", - "firstname": "Michael", - "surname": "Rosbash", - "motivation": "\"for their discoveries of molecular mechanisms controlling the circadian rhythm\"", - "share": "3" - }, - { - "id": "940", - "firstname": "Michael W.", - "surname": "Young", - "motivation": "\"for their discoveries of molecular mechanisms controlling the circadian rhythm\"", - "share": "3" - } - ], - "overallMotivation": null, - "prize_id": 42, - "year": 2017 - } - ] - } -] \ No newline at end of file + { + "rows": [ + { + "overallMotivation": null, + "prize_id": 37, + "year": 2017 + }, + { + "overallMotivation": null, + "prize_id": 38, + "year": 2017 + }, + { + "overallMotivation": null, + "prize_id": 39, + "year": 2017 + }, + { + "overallMotivation": null, + "prize_id": 40, + "year": 2017 + }, + { + "overallMotivation": null, + "prize_id": 41, + "year": 2017 + }, + { + "overallMotivation": null, + "prize_id": 42, + "year": 2017 + } + ] + } +] diff --git a/ndc-test-snapshots/query/nobel_laureates_predicate_on_year_orderby_test/request.json b/ndc-test-snapshots/query/nobel_laureates_predicate_on_year_orderby_test/request.json index 5b5bc64..8e1e6ff 100644 --- a/ndc-test-snapshots/query/nobel_laureates_predicate_on_year_orderby_test/request.json +++ b/ndc-test-snapshots/query/nobel_laureates_predicate_on_year_orderby_test/request.json @@ -2,11 +2,6 @@ "collection": "TestNobelLaureates", "query": { "fields": { - "laureates": { - "type": "column", - "column": "laureates", - "fields": null - }, "overallMotivation": { "type": "column", "column": "overallMotivation", diff --git a/ndc-test-snapshots/query/nobel_laureates_simple_asc_orderby_test/expected.json b/ndc-test-snapshots/query/nobel_laureates_simple_asc_orderby_test/expected.json index f318f08..d6e6d75 100644 --- a/ndc-test-snapshots/query/nobel_laureates_simple_asc_orderby_test/expected.json +++ b/ndc-test-snapshots/query/nobel_laureates_simple_asc_orderby_test/expected.json @@ -1,221 +1,56 @@ [ - { - "rows": [ - { - "laureates": [ - { - "id": "1029", - "firstname": "Moungi", - "surname": "Bawendi", - "motivation": "\"for the discovery and synthesis of quantum dots\"", - "share": "3" - }, - { - "id": "1030", - "firstname": "Louis", - "surname": "Brus", - "motivation": "\"for the discovery and synthesis of quantum dots\"", - "share": "3" - }, - { - "id": "1031", - "firstname": "Aleksey", - "surname": "Yekimov", - "motivation": "\"for the discovery and synthesis of quantum dots\"", - "share": "3" - } - ], - "overallMotivation": null, - "prize_id": 1, - "year": 2023 - }, - { - "laureates": [ - { - "id": "1034", - "firstname": "Claudia", - "surname": "Goldin", - "motivation": "\"for having advanced our understanding of women’s labour market outcomes\"", - "share": "1" - } - ], - "overallMotivation": null, - "prize_id": 2, - "year": 2023 - }, - { - "laureates": [ - { - "id": "1032", - "firstname": "Jon", - "surname": "Fosse", - "motivation": "\"for his innovative plays and prose which give voice to the unsayable\"", - "share": "1" - } - ], - "overallMotivation": null, - "prize_id": 3, - "year": 2023 - }, - { - "laureates": [ - { - "id": "1033", - "firstname": "Narges", - "surname": "Mohammadi", - "motivation": "\"for her fight against the oppression of women in Iran and her fight to promote human rights and freedom for all\"", - "share": "1" - } - ], - "overallMotivation": null, - "prize_id": 4, - "year": 2023 - }, - { - "laureates": [ - { - "id": "1026", - "firstname": "Pierre", - "surname": "Agostini", - "motivation": "\"for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter\"", - "share": "3" - }, - { - "id": "1027", - "firstname": "Ferenc", - "surname": "Krausz", - "motivation": "\"for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter\"", - "share": "3" - }, - { - "id": "1028", - "firstname": "Anne", - "surname": "L’Huillier", - "motivation": "\"for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter\"", - "share": "3" - } - ], - "overallMotivation": null, - "prize_id": 5, - "year": 2023 - }, - { - "laureates": [ - { - "id": "1024", - "firstname": "Katalin", - "surname": "Karikó", - "motivation": "\"for their discoveries concerning nucleoside base modifications that enabled the development of effective mRNA vaccines against COVID-19\"", - "share": "2" - }, - { - "id": "1025", - "firstname": "Drew", - "surname": "Weissman", - "motivation": "\"for their discoveries concerning nucleoside base modifications that enabled the development of effective mRNA vaccines against COVID-19\"", - "share": "2" - } - ], - "overallMotivation": null, - "prize_id": 6, - "year": 2023 - }, - { - "laureates": [ - { - "id": "1015", - "firstname": "Carolyn", - "surname": "Bertozzi", - "motivation": "\"for the development of click chemistry and bioorthogonal chemistry\"", - "share": "3" - }, - { - "id": "1016", - "firstname": "Morten", - "surname": "Meldal", - "motivation": "\"for the development of click chemistry and bioorthogonal chemistry\"", - "share": "3" - }, - { - "id": "743", - "firstname": "Barry", - "surname": "Sharpless", - "motivation": "\"for the development of click chemistry and bioorthogonal chemistry\"", - "share": "3" - } - ], - "overallMotivation": null, - "prize_id": 7, - "year": 2022 - }, - { - "laureates": [ - { - "id": "1021", - "firstname": "Ben", - "surname": "Bernanke", - "motivation": "\"for research on banks and financial crises\"", - "share": "3" - }, - { - "id": "1022", - "firstname": "Douglas", - "surname": "Diamond", - "motivation": "\"for research on banks and financial crises\"", - "share": "3" - }, - { - "id": "1023", - "firstname": "Philip", - "surname": "Dybvig", - "motivation": "\"for research on banks and financial crises\"", - "share": "3" - } - ], - "overallMotivation": null, - "prize_id": 8, - "year": 2022 - }, - { - "laureates": [ - { - "id": "1017", - "firstname": "Annie", - "surname": "Ernaux", - "motivation": "\"for the courage and clinical acuity with which she uncovers the roots, estrangements and collective restraints of personal memory\"", - "share": "1" - } - ], - "overallMotivation": null, - "prize_id": 9, - "year": 2022 - }, - { - "laureates": [ - { - "id": "1018", - "firstname": "Ales", - "surname": "Bialiatski ", - "motivation": "\"The Peace Prize laureates represent civil society in their home countries. They have for many years promoted the right to criticise power and protect the fundamental rights of citizens. They have made an outstanding effort to document war crimes, human right abuses and the abuse of power. Together they demonstrate the significance of civil society for peace and democracy.\"", - "share": "3" - }, - { - "id": "1019", - "motivation": "\"The Peace Prize laureates represent civil society in their home countries. They have for many years promoted the right to criticise power and protect the fundamental rights of citizens. They have made an outstanding effort to document war crimes, human right abuses and the abuse of power. Together they demonstrate the significance of civil society for peace and democracy.\"", - "share": "3", - "firstname": "Memorial" - }, - { - "id": "1020", - "motivation": "\"The Peace Prize laureates represent civil society in their home countries. They have for many years promoted the right to criticise power and protect the fundamental rights of citizens. They have made an outstanding effort to document war crimes, human right abuses and the abuse of power. Together they demonstrate the significance of civil society for peace and democracy.\"", - "share": "3", - "firstname": "Center for Civil Liberties" - } - ], - "overallMotivation": null, - "prize_id": 10, - "year": 2022 - } - ] - } -] \ No newline at end of file + { + "rows": [ + { + "overallMotivation": null, + "prize_id": 1, + "year": 2023 + }, + { + "overallMotivation": null, + "prize_id": 2, + "year": 2023 + }, + { + "overallMotivation": null, + "prize_id": 3, + "year": 2023 + }, + { + "overallMotivation": null, + "prize_id": 4, + "year": 2023 + }, + { + "overallMotivation": null, + "prize_id": 5, + "year": 2023 + }, + { + "overallMotivation": null, + "prize_id": 6, + "year": 2023 + }, + { + "overallMotivation": null, + "prize_id": 7, + "year": 2022 + }, + { + "overallMotivation": null, + "prize_id": 8, + "year": 2022 + }, + { + "overallMotivation": null, + "prize_id": 9, + "year": 2022 + }, + { + "overallMotivation": null, + "prize_id": 10, + "year": 2022 + } + ] + } +] diff --git a/ndc-test-snapshots/query/nobel_laureates_simple_asc_orderby_test/request.json b/ndc-test-snapshots/query/nobel_laureates_simple_asc_orderby_test/request.json index a29f353..aa665d7 100644 --- a/ndc-test-snapshots/query/nobel_laureates_simple_asc_orderby_test/request.json +++ b/ndc-test-snapshots/query/nobel_laureates_simple_asc_orderby_test/request.json @@ -2,11 +2,7 @@ "collection": "TestNobelLaureates", "query": { "fields": { - "laureates": { - "type": "column", - "column": "laureates", - "fields": null - }, + "overallMotivation": { "type": "column", "column": "overallMotivation", diff --git a/ndc-test-snapshots/query/nobel_laureates_simple_limit_orderby_test/expected.json b/ndc-test-snapshots/query/nobel_laureates_simple_limit_orderby_test/expected.json index c9c92b7..1e0bf0f 100644 --- a/ndc-test-snapshots/query/nobel_laureates_simple_limit_orderby_test/expected.json +++ b/ndc-test-snapshots/query/nobel_laureates_simple_limit_orderby_test/expected.json @@ -1,198 +1,46 @@ [ - { - "rows": [ - { - "year_8595": 2007, - "laureates_8171": [ - { - "id": "818", - "motivation": "\"for their efforts to build up and disseminate greater knowledge about man-made climate change, and to lay the foundations for the measures that are needed to counteract such change\"", - "share": "2", - "firstname": "Intergovernmental Panel on Climate Change" - }, - { - "id": "819", - "firstname": "Al", - "surname": "Gore", - "motivation": "\"for their efforts to build up and disseminate greater knowledge about man-made climate change, and to lay the foundations for the measures that are needed to counteract such change\"", - "share": "2" - } - ], - "overallMotivation_2599": null - }, - { - "year_8595": 2007, - "laureates_8171": [ - { - "id": "817", - "firstname": "Doris", - "surname": "Lessing", - "motivation": "\"that epicist of the female experience, who with scepticism, fire and visionary power has subjected a divided civilisation to scrutiny\"", - "share": "1" - } - ], - "overallMotivation_2599": null - }, - { - "year_8595": 2007, - "laureates_8171": [ - { - "id": "820", - "firstname": "Leonid", - "surname": "Hurwicz", - "motivation": "\"for having laid the foundations of mechanism design theory\"", - "share": "3" - }, - { - "id": "821", - "firstname": "Eric S.", - "surname": "Maskin", - "motivation": "\"for having laid the foundations of mechanism design theory\"", - "share": "3" - }, - { - "id": "822", - "firstname": "Roger B.", - "surname": "Myerson", - "motivation": "\"for having laid the foundations of mechanism design theory\"", - "share": "3" - } - ], - "overallMotivation_2599": null - }, - { - "year_8595": 2007, - "laureates_8171": [ - { - "id": "816", - "firstname": "Gerhard", - "surname": "Ertl", - "motivation": "\"for his studies of chemical processes on solid surfaces\"", - "share": "1" - } - ], - "overallMotivation_2599": null - }, - { - "year_8595": 2008, - "laureates_8171": [ - { - "id": "823", - "firstname": "Harald", - "surname": "zur Hausen", - "motivation": "\"for his discovery of human papilloma viruses causing cervical cancer\"", - "share": "2" - }, - { - "id": "824", - "firstname": "Françoise", - "surname": "Barré-Sinoussi", - "motivation": "\"for their discovery of human immunodeficiency virus\"", - "share": "4" - }, - { - "id": "825", - "firstname": "Luc", - "surname": "Montagnier", - "motivation": "\"for their discovery of human immunodeficiency virus\"", - "share": "4" - } - ], - "overallMotivation_2599": null - }, - { - "year_8595": 2008, - "laureates_8171": [ - { - "id": "826", - "firstname": "Yoichiro", - "surname": "Nambu", - "motivation": "\"for the discovery of the mechanism of spontaneous broken symmetry in subatomic physics\"", - "share": "2" - }, - { - "id": "827", - "firstname": "Makoto", - "surname": "Kobayashi", - "motivation": "\"for the discovery of the origin of the broken symmetry which predicts the existence of at least three families of quarks in nature\"", - "share": "4" - }, - { - "id": "828", - "firstname": "Toshihide", - "surname": "Maskawa", - "motivation": "\"for the discovery of the origin of the broken symmetry which predicts the existence of at least three families of quarks in nature\"", - "share": "4" - } - ], - "overallMotivation_2599": null - }, - { - "year_8595": 2008, - "laureates_8171": [ - { - "id": "833", - "firstname": "Martti", - "surname": "Ahtisaari", - "motivation": "\"for his important efforts, on several continents and over more than three decades, to resolve international conflicts\"", - "share": "1" - } - ], - "overallMotivation_2599": null - }, - { - "year_8595": 2008, - "laureates_8171": [ - { - "id": "832", - "firstname": "Jean-Marie Gustave", - "surname": "Le Clézio", - "motivation": "\"author of new departures, poetic adventure and sensual ecstasy, explorer of a humanity beyond and below the reigning civilization\"", - "share": "1" - } - ], - "overallMotivation_2599": null - }, - { - "year_8595": 2008, - "laureates_8171": [ - { - "id": "834", - "firstname": "Paul", - "surname": "Krugman", - "motivation": "\"for his analysis of trade patterns and location of economic activity\"", - "share": "1" - } - ], - "overallMotivation_2599": null - }, - { - "year_8595": 2008, - "laureates_8171": [ - { - "id": "829", - "firstname": "Osamu", - "surname": "Shimomura", - "motivation": "\"for the discovery and development of the green fluorescent protein, GFP\"", - "share": "3" - }, - { - "id": "830", - "firstname": "Martin", - "surname": "Chalfie", - "motivation": "\"for the discovery and development of the green fluorescent protein, GFP\"", - "share": "3" - }, - { - "id": "831", - "firstname": "Roger Y.", - "surname": "Tsien", - "motivation": "\"for the discovery and development of the green fluorescent protein, GFP\"", - "share": "3" - } - ], - "overallMotivation_2599": null - } - ] - } -] \ No newline at end of file + { + "rows": [ + { + "year_8595": 2007, + "overallMotivation_2599": null + }, + { + "year_8595": 2007, + "overallMotivation_2599": null + }, + { + "year_8595": 2007, + "overallMotivation_2599": null + }, + { + "year_8595": 2007, + "overallMotivation_2599": null + }, + { + "year_8595": 2008, + "overallMotivation_2599": null + }, + { + "year_8595": 2008, + "overallMotivation_2599": null + }, + { + "year_8595": 2008, + "overallMotivation_2599": null + }, + { + "year_8595": 2008, + "overallMotivation_2599": null + }, + { + "year_8595": 2008, + "overallMotivation_2599": null + }, + { + "year_8595": 2008, + "overallMotivation_2599": null + } + ] + } +] diff --git a/ndc-test-snapshots/query/nobel_laureates_simple_limit_orderby_test/request.json b/ndc-test-snapshots/query/nobel_laureates_simple_limit_orderby_test/request.json index 4c488f5..e365c48 100644 --- a/ndc-test-snapshots/query/nobel_laureates_simple_limit_orderby_test/request.json +++ b/ndc-test-snapshots/query/nobel_laureates_simple_limit_orderby_test/request.json @@ -7,11 +7,6 @@ "column": "year", "fields": null }, - "laureates_8171": { - "type": "column", - "column": "laureates", - "fields": null - }, "overallMotivation_2599": { "type": "column", "column": "overallMotivation", diff --git a/ndc-test-snapshots/query/nobel_laureates_simple_predicate_on_prize_id/expected.json b/ndc-test-snapshots/query/nobel_laureates_simple_predicate_on_prize_id/expected.json index 0928583..710dc0c 100644 --- a/ndc-test-snapshots/query/nobel_laureates_simple_predicate_on_prize_id/expected.json +++ b/ndc-test-snapshots/query/nobel_laureates_simple_predicate_on_prize_id/expected.json @@ -1,34 +1,109 @@ [ - { - "rows": [ - { - "laureates": [ - { - "id": "963", - "firstname": "Frances H.", - "surname": "Arnold", - "motivation": "\"for the directed evolution of enzymes\"", - "share": "2" - }, - { - "id": "964", - "firstname": "George P.", - "surname": "Smith", - "motivation": "\"for the phage display of peptides and antibodies\"", - "share": "4" - }, - { - "id": "965", - "firstname": "Sir Gregory P.", - "surname": "Winter", - "motivation": "\"for the phage display of peptides and antibodies\"", - "share": "4" - } - ], - "overallMotivation": null, - "prize_id": 31, - "year": 2018 - } - ] - } -] \ No newline at end of file + { + "rows": [ + { + "laureates": [ + { + "id": "963", + "firstname": "Frances H.", + "surname": "Arnold", + "motivation": "\"for the directed evolution of enzymes\"", + "share": "2", + "birth": { + "year": 1977, + "country": { + "city": "Paris", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2019, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2014, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Fields Medal", + "year": 2007, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + } + ] + }, + { + "id": "964", + "firstname": "George P.", + "surname": "Smith", + "motivation": "\"for the phage display of peptides and antibodies\"", + "share": "4", + "birth": { + "year": 1982, + "country": { + "city": "Los Angeles", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2014, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + } + ] + }, + { + "id": "965", + "firstname": "Sir Gregory P.", + "surname": "Winter", + "motivation": "\"for the phage display of peptides and antibodies\"", + "share": "4", + "birth": { + "year": 2022, + "country": { + "city": "Sydney", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2016, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2020, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + } + ] + } + ], + "overallMotivation": null, + "prize_id": 31, + "year": 2018 + } + ] + } +] diff --git a/ndc-test-snapshots/schema b/ndc-test-snapshots/schema deleted file mode 100644 index c70e43b..0000000 --- a/ndc-test-snapshots/schema +++ /dev/null @@ -1,341 +0,0 @@ -{ - "scalar_types": { - "Boolean": { - "aggregate_functions": { - "bool_and": { - "result_type": { - "type": "named", - "name": "Boolean" - } - }, - "bool_not": { - "result_type": { - "type": "named", - "name": "Boolean" - } - }, - "bool_or": { - "result_type": { - "type": "named", - "name": "Boolean" - } - } - }, - "comparison_operators": { - "eq": { - "type": "equal" - }, - "neq": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "Boolean" - } - } - } - }, - "Integer": { - "aggregate_functions": { - "avg": { - "result_type": { - "type": "named", - "name": "Integer" - } - }, - "count": { - "result_type": { - "type": "named", - "name": "Integer" - } - }, - "max": { - "result_type": { - "type": "named", - "name": "Integer" - } - }, - "min": { - "result_type": { - "type": "named", - "name": "Integer" - } - }, - "sum": { - "result_type": { - "type": "named", - "name": "Integer" - } - } - }, - "comparison_operators": { - "eq": { - "type": "equal" - }, - "gt": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "Integer" - } - }, - "gte": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "Integer" - } - }, - "lt": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "Integer" - } - }, - "lte": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "Integer" - } - }, - "neq": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "Integer" - } - } - } - }, - "Number": { - "aggregate_functions": { - "avg": { - "result_type": { - "type": "named", - "name": "Number" - } - }, - "count": { - "result_type": { - "type": "named", - "name": "Number" - } - }, - "max": { - "result_type": { - "type": "named", - "name": "Number" - } - }, - "min": { - "result_type": { - "type": "named", - "name": "Number" - } - }, - "sum": { - "result_type": { - "type": "named", - "name": "Number" - } - } - }, - "comparison_operators": { - "eq": { - "type": "equal" - }, - "gt": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "Number" - } - }, - "gte": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "Number" - } - }, - "lt": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "Number" - } - }, - "lte": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "Number" - } - }, - "neq": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "Number" - } - } - } - }, - "String": { - "aggregate_functions": {}, - "comparison_operators": { - "contains": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "String" - } - }, - "endswith": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "String" - } - }, - "eq": { - "type": "equal" - }, - "gt": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "String" - } - }, - "gte": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "String" - } - }, - "lt": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "String" - } - }, - "lte": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "String" - } - }, - "neq": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "String" - } - }, - "regexmatch": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "String" - } - }, - "startswith": { - "type": "custom", - "argument_type": { - "type": "named", - "name": "String" - } - } - } - } - }, - "object_types": { - "Laureate": { - "fields": { - "firstname": { - "type": { - "type": "named", - "name": "String" - } - }, - "id": { - "type": { - "type": "named", - "name": "String" - } - }, - "motivation": { - "type": { - "type": "named", - "name": "String" - } - }, - "share": { - "type": { - "type": "named", - "name": "String" - } - }, - "surname": { - "type": { - "type": "named", - "name": "String" - } - } - } - }, - "TestNobelLaureates": { - "fields": { - "id": { - "type": { - "type": "named", - "name": "String" - } - }, - "laureates": { - "type": { - "type": "array", - "element_type": { - "type": "named", - "name": "Laureate" - } - } - }, - "overallMotivation": { - "type": { - "type": "named", - "name": "String" - } - }, - "prize_id": { - "type": { - "type": "named", - "name": "Number" - } - }, - "year": { - "type": { - "type": "named", - "name": "Number" - } - } - } - } - }, - "collections": [ - { - "name": "TestNobelLaureates", - "arguments": {}, - "type": "TestNobelLaureates", - "uniqueness_constraints": {}, - "foreign_keys": {} - } - ], - "functions": [], - "procedures": [] -} diff --git a/package-lock.json b/package-lock.json index a126192..226cb96 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,9 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@azure/cosmos": "^4.0.0", + "@azure/cosmos": "^4.1.0", "@azure/identity": "^4.0.1", - "@hasura/ndc-sdk-typescript": "^6.0.0", + "@hasura/ndc-sdk-typescript": "^6.1.0", "dotenv": "^16.4.5", "quicktype-core": "^23.0.104", "ts-node": "^10.9.2", @@ -24,12 +24,14 @@ "@apidevtools/json-schema-ref-parser": "^11.5.4", "@types/chai": "^4.3.11", "@types/chai-as-promised": "^7.1.8", + "@types/fs-extra": "^11.0.4", "@types/json-pointer": "^1.0.34", "@types/jsonpath": "^0.2.4", "@types/mocha": "^10.0.6", "@types/node": "^20.11.17", "chai-as-promised": "^7.1.1", "commander": "^11.0.0", + "fs-extra": "^11.2.0", "mocha": "^10.3.0", "nodemon": "^3.1.0", "nyc": "^15.1.0", @@ -78,13 +80,13 @@ } }, "node_modules/@azure/core-auth": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.6.0.tgz", - "integrity": "sha512-3X9wzaaGgRaBCwhLQZDtFp5uLIXCPrGbwJNWPPugvL4xbIGgScv77YzzxToKGLAKvG9amDoofMoP+9hsH1vs1w==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.7.2.tgz", + "integrity": "sha512-Igm/S3fDYmnMq1uKS38Ae1/m37B3zigdlZw+kocwEhh5GjyKjPrXKO2J6rzpC1wAxrNil/jX9BJRqBshyjnF3g==", "dependencies": { "@azure/abort-controller": "^2.0.0", "@azure/core-util": "^1.1.0", - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" @@ -102,46 +104,46 @@ } }, "node_modules/@azure/core-client": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.8.0.tgz", - "integrity": "sha512-+gHS3gEzPlhyQBMoqVPOTeNH031R5DM/xpCvz72y38C09rg4Hui/1sJS/ujoisDZbbSHyuRLVWdFlwL0pIFwbg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.9.2.tgz", + "integrity": "sha512-kRdry/rav3fUKHl/aDLd/pDLcB+4pOFwPPTVEExuMyaI5r+JBbMWqRbCY1pn5BniDaU3lRxO9eaQ1AmSMehl/w==", "dependencies": { "@azure/abort-controller": "^2.0.0", "@azure/core-auth": "^1.4.0", "@azure/core-rest-pipeline": "^1.9.1", "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", + "@azure/core-util": "^1.6.1", "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@azure/core-client/node_modules/@azure/abort-controller": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.0.0.tgz", - "integrity": "sha512-RP/mR/WJchR+g+nQFJGOec+nzeN/VvjlwbinccoqfhTsTHbb8X5+mLDp48kHT0ueyum0BNSwGm0kX0UZuIqTGg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", "dependencies": { - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@azure/core-rest-pipeline": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.14.0.tgz", - "integrity": "sha512-Tp4M6NsjCmn9L5p7HsW98eSOS7A0ibl3e5ntZglozT0XuD/0y6i36iW829ZbBq0qihlGgfaeFpkLjZ418KDm1Q==", + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.16.3.tgz", + "integrity": "sha512-VxLk4AHLyqcHsfKe4MZ6IQ+D+ShuByy+RfStKfSjxJoL3WBWq17VNmrz8aT8etKzqc2nAeIyLxScjpzsS4fz8w==", "dependencies": { "@azure/abort-controller": "^2.0.0", "@azure/core-auth": "^1.4.0", "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.3.0", + "@azure/core-util": "^1.9.0", "@azure/logger": "^1.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "tslib": "^2.2.0" + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" @@ -159,23 +161,23 @@ } }, "node_modules/@azure/core-tracing": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz", - "integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.1.2.tgz", + "integrity": "sha512-dawW9ifvWAWmUm9/h+/UQ2jrdvjCJ7VJEuCJ6XVNudzcOwm53BFZH4Q845vjfgoUAM8ZxokvVNxNxAITc502YA==", "dependencies": { - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=12.0.0" + "node": ">=18.0.0" } }, "node_modules/@azure/core-util": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.7.0.tgz", - "integrity": "sha512-Zq2i3QO6k9DA8vnm29mYM4G8IE9u1mhF1GUabVEqPNX8Lj833gdxQ2NAFxt2BZsfAL+e9cT8SyVN7dFVJ/Hf0g==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.9.2.tgz", + "integrity": "sha512-l1Qrqhi4x1aekkV+OlcqsJa4AnAkj5p0JV8omgwjaV9OAbP41lvrMvs+CptfetKkeEaGRGSzby7sjPZEX7+kkQ==", "dependencies": { "@azure/abort-controller": "^2.0.0", - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" @@ -193,42 +195,50 @@ } }, "node_modules/@azure/cosmos": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-4.0.0.tgz", - "integrity": "sha512-/Z27p1+FTkmjmm8jk90zi/HrczPHw2t8WecFnsnTe4xGocWl0Z4clP0YlLUTJPhRLWYa5upwD9rMvKJkS1f1kg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-4.1.0.tgz", + "integrity": "sha512-+m085WKIGkf6wyw4vT85FFXl9j3U35u+LFFVwmLqfPbolnQAtoX24cowXz+vseW4BWKyx6Lamb+Zz+jl69zn6g==", "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-rest-pipeline": "^1.2.0", - "@azure/core-tracing": "^1.0.0", - "debug": "^4.1.1", + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.7.1", + "@azure/core-rest-pipeline": "^1.15.1", + "@azure/core-tracing": "^1.1.1", + "@azure/core-util": "^1.8.1", "fast-json-stable-stringify": "^2.1.0", - "jsbi": "^3.1.3", - "node-abort-controller": "^3.0.0", - "priorityqueuejs": "^1.0.0", - "semaphore": "^1.0.5", - "tslib": "^2.2.0", - "universal-user-agent": "^6.0.0", - "uuid": "^8.3.0" + "jsbi": "^4.3.0", + "priorityqueuejs": "^2.0.0", + "semaphore": "^1.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/@azure/cosmos/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@azure/identity": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.0.1.tgz", - "integrity": "sha512-yRdgF03SFLqUMZZ1gKWt0cs0fvrDIkq2bJ6Oidqcoo5uM85YMBnXWMzYKK30XqIT76lkFyAaoAAy5knXhrG4Lw==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.4.1.tgz", + "integrity": "sha512-DwnG4cKFEM7S3T+9u05NstXU/HN0dk45kPOinUyNKsn5VWwpXd9sbPKEg6kgJzGbm1lMuhx9o31PVbCtM5sfBA==", "dependencies": { "@azure/abort-controller": "^1.0.0", "@azure/core-auth": "^1.5.0", - "@azure/core-client": "^1.4.0", + "@azure/core-client": "^1.9.2", "@azure/core-rest-pipeline": "^1.1.0", "@azure/core-tracing": "^1.0.0", "@azure/core-util": "^1.3.0", "@azure/logger": "^1.0.0", - "@azure/msal-browser": "^3.5.0", - "@azure/msal-node": "^2.5.1", + "@azure/msal-browser": "^3.14.0", + "@azure/msal-node": "^2.9.2", "events": "^3.0.0", "jws": "^4.0.0", "open": "^8.0.0", @@ -251,30 +261,52 @@ } }, "node_modules/@azure/msal-browser": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.10.0.tgz", - "integrity": "sha512-mnmi8dCXVNZI+AGRq0jKQ3YiodlIC4W9npr6FCB9WN6NQT+6rq+cIlxgUb//BjLyzKsnYo+i4LROGeMyU+6v1A==", +<<<<<<< HEAD + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.21.0.tgz", + "integrity": "sha512-BAwcFsVvOrYzKuUZHhFuvRykUmQGq6lDxst2qGnjxnpNZc3d/tnVPcmhgvUdeKl28VSE0ltgBzT3HkdpDtz9rg==", "dependencies": { - "@azure/msal-common": "14.7.1" + "@azure/msal-common": "14.14.1" +======= + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.23.0.tgz", + "integrity": "sha512-+QgdMvaeEpdtgRTD7AHHq9aw8uga7mXVHV1KshO1RQ2uI5B55xJ4aEpGlg/ga3H+0arEVcRfT4ZVmX7QLXiCVw==", + "dependencies": { + "@azure/msal-common": "14.14.2" +>>>>>>> 0314eec... Fix NDC tests (#40) }, "engines": { "node": ">=0.8.0" } }, "node_modules/@azure/msal-common": { - "version": "14.7.1", - "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.7.1.tgz", - "integrity": "sha512-v96btzjM7KrAu4NSEdOkhQSTGOuNUIIsUdB8wlyB9cdgl5KqEKnTonHUZ8+khvZ6Ap542FCErbnTyDWl8lZ2rA==", +<<<<<<< HEAD + "version": "14.14.1", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.14.1.tgz", + "integrity": "sha512-2Q3tqNz/PZLfSr8BvcHZVpRRfSn4MjGSqjj9J+HlBsmbf1Uu4P0WeXnemjTJwwx9KrmplsrN3UkZ/LPOR720rw==", +======= + "version": "14.14.2", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.14.2.tgz", + "integrity": "sha512-XV0P5kSNwDwCA/SjIxTe9mEAsKB0NqGNSuaVrkCCE2lAyBr/D6YtD80Vkdp4tjWnPFwjzkwldjr1xU/facOJog==", +>>>>>>> 0314eec... Fix NDC tests (#40) "engines": { "node": ">=0.8.0" } }, "node_modules/@azure/msal-node": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.6.4.tgz", - "integrity": "sha512-nNvEPx009/80UATCToF+29NZYocn01uKrB91xtFr7bSqkqO1PuQGXRyYwryWRztUrYZ1YsSbw9A+LmwOhpVvcg==", - "dependencies": { - "@azure/msal-common": "14.7.1", +<<<<<<< HEAD + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.13.0.tgz", + "integrity": "sha512-DhP97ycs7qlCVzzzWGzJiwAFyFj5okno74E4FUZ61oCLfKh4IxA1kxirqzrWuYZWpBe9HVPL6GA4NvmlEOBN5Q==", + "dependencies": { + "@azure/msal-common": "14.14.1", +======= + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.13.1.tgz", + "integrity": "sha512-sijfzPNorKt6+9g1/miHwhj6Iapff4mPQx1azmmZExgzUROqWTM1o3ACyxDja0g47VpowFy/sxTM/WsuCyXTiw==", + "dependencies": { + "@azure/msal-common": "14.14.2", +>>>>>>> 0314eec... Fix NDC tests (#40) "jsonwebtoken": "^9.0.0", "uuid": "^8.3.0" }, @@ -822,9 +854,9 @@ } }, "node_modules/@hasura/ndc-sdk-typescript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@hasura/ndc-sdk-typescript/-/ndc-sdk-typescript-6.0.0.tgz", - "integrity": "sha512-iLC7IAh2rsW7iyt6swLyOpk0zL32d5LeGN+KSJNJEO6n8eXKsjQpJZBsqKEYOyGcfSlbNqTC1qsobbtwe7Bjyw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@hasura/ndc-sdk-typescript/-/ndc-sdk-typescript-6.1.0.tgz", + "integrity": "sha512-kW+DgohuVzbYuOBp9fqTz0jzdZVlPfsUMdT3HKcXxUlUCvHHuTHffFTxW8TvR/JGk8qGYzA9rbnKelkFQOXf/A==", "dependencies": { "@json-schema-tools/meta-schema": "^1.7.0", "@opentelemetry/api": "^1.8.0", @@ -1986,14 +2018,6 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "engines": { - "node": ">= 10" - } - }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -2029,6 +2053,16 @@ "@types/chai": "*" } }, + "node_modules/@types/fs-extra": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", + "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", + "dev": true, + "dependencies": { + "@types/jsonfile": "*", + "@types/node": "*" + } + }, "node_modules/@types/json-pointer": { "version": "1.0.34", "resolved": "https://registry.npmjs.org/@types/json-pointer/-/json-pointer-1.0.34.tgz", @@ -2041,6 +2075,15 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/jsonfile": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", + "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/jsonpath": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/@types/jsonpath/-/jsonpath-0.2.4.tgz", @@ -2121,14 +2164,14 @@ } }, "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dependencies": { - "debug": "4" + "debug": "^4.3.4" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 14" } }, "node_modules/aggregate-error": { @@ -2325,12 +2368,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -2947,9 +2990,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -3054,6 +3097,20 @@ } ] }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3220,28 +3277,27 @@ "dev": true }, "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dependencies": { - "agent-base": "6", + "agent-base": "^7.0.2", "debug": "4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/ieee754": { @@ -3707,9 +3763,9 @@ } }, "node_modules/jsbi": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.2.5.tgz", - "integrity": "sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ==" + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-4.3.0.tgz", + "integrity": "sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g==" }, "node_modules/jsesc": { "version": "2.5.2", @@ -3748,6 +3804,18 @@ "node": ">=6" } }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/jsonwebtoken": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", @@ -4071,11 +4139,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "node_modules/node-abort-controller": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" - }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -4744,9 +4807,9 @@ } }, "node_modules/priorityqueuejs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-1.0.0.tgz", - "integrity": "sha512-lg++21mreCEOuGWTbO5DnJKAdxfjrdN0S9ysoW9SzdSJvbkWpkaDdpG/cdsPCsEnoLUwmd9m3WcZhngW7yKA2g==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-2.0.0.tgz", + "integrity": "sha512-19BMarhgpq3x4ccvVi8k2QpJZcymo/iFUcrhPd4V96kYGovOdTsWwy7fxChYi4QY+m2EnGBWSX9Buakz+tWNQQ==" }, "node_modules/process": { "version": "0.11.10", @@ -5736,10 +5799,14 @@ "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" }, - "node_modules/universal-user-agent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", - "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==" + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } }, "node_modules/update-browserslist-db": { "version": "1.0.13", @@ -6044,13 +6111,13 @@ } }, "@azure/core-auth": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.6.0.tgz", - "integrity": "sha512-3X9wzaaGgRaBCwhLQZDtFp5uLIXCPrGbwJNWPPugvL4xbIGgScv77YzzxToKGLAKvG9amDoofMoP+9hsH1vs1w==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.7.2.tgz", + "integrity": "sha512-Igm/S3fDYmnMq1uKS38Ae1/m37B3zigdlZw+kocwEhh5GjyKjPrXKO2J6rzpC1wAxrNil/jX9BJRqBshyjnF3g==", "requires": { "@azure/abort-controller": "^2.0.0", "@azure/core-util": "^1.1.0", - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "dependencies": { "@azure/abort-controller": { @@ -6064,42 +6131,42 @@ } }, "@azure/core-client": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.8.0.tgz", - "integrity": "sha512-+gHS3gEzPlhyQBMoqVPOTeNH031R5DM/xpCvz72y38C09rg4Hui/1sJS/ujoisDZbbSHyuRLVWdFlwL0pIFwbg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.9.2.tgz", + "integrity": "sha512-kRdry/rav3fUKHl/aDLd/pDLcB+4pOFwPPTVEExuMyaI5r+JBbMWqRbCY1pn5BniDaU3lRxO9eaQ1AmSMehl/w==", "requires": { "@azure/abort-controller": "^2.0.0", "@azure/core-auth": "^1.4.0", "@azure/core-rest-pipeline": "^1.9.1", "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", + "@azure/core-util": "^1.6.1", "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "dependencies": { "@azure/abort-controller": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.0.0.tgz", - "integrity": "sha512-RP/mR/WJchR+g+nQFJGOec+nzeN/VvjlwbinccoqfhTsTHbb8X5+mLDp48kHT0ueyum0BNSwGm0kX0UZuIqTGg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", "requires": { - "tslib": "^2.2.0" + "tslib": "^2.6.2" } } } }, "@azure/core-rest-pipeline": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.14.0.tgz", - "integrity": "sha512-Tp4M6NsjCmn9L5p7HsW98eSOS7A0ibl3e5ntZglozT0XuD/0y6i36iW829ZbBq0qihlGgfaeFpkLjZ418KDm1Q==", + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.16.3.tgz", + "integrity": "sha512-VxLk4AHLyqcHsfKe4MZ6IQ+D+ShuByy+RfStKfSjxJoL3WBWq17VNmrz8aT8etKzqc2nAeIyLxScjpzsS4fz8w==", "requires": { "@azure/abort-controller": "^2.0.0", "@azure/core-auth": "^1.4.0", "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.3.0", + "@azure/core-util": "^1.9.0", "@azure/logger": "^1.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "tslib": "^2.2.0" + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" }, "dependencies": { "@azure/abort-controller": { @@ -6113,20 +6180,20 @@ } }, "@azure/core-tracing": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz", - "integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.1.2.tgz", + "integrity": "sha512-dawW9ifvWAWmUm9/h+/UQ2jrdvjCJ7VJEuCJ6XVNudzcOwm53BFZH4Q845vjfgoUAM8ZxokvVNxNxAITc502YA==", "requires": { - "tslib": "^2.2.0" + "tslib": "^2.6.2" } }, "@azure/core-util": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.7.0.tgz", - "integrity": "sha512-Zq2i3QO6k9DA8vnm29mYM4G8IE9u1mhF1GUabVEqPNX8Lj833gdxQ2NAFxt2BZsfAL+e9cT8SyVN7dFVJ/Hf0g==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.9.2.tgz", + "integrity": "sha512-l1Qrqhi4x1aekkV+OlcqsJa4AnAkj5p0JV8omgwjaV9OAbP41lvrMvs+CptfetKkeEaGRGSzby7sjPZEX7+kkQ==", "requires": { "@azure/abort-controller": "^2.0.0", - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "dependencies": { "@azure/abort-controller": { @@ -6140,39 +6207,46 @@ } }, "@azure/cosmos": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-4.0.0.tgz", - "integrity": "sha512-/Z27p1+FTkmjmm8jk90zi/HrczPHw2t8WecFnsnTe4xGocWl0Z4clP0YlLUTJPhRLWYa5upwD9rMvKJkS1f1kg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-4.1.0.tgz", + "integrity": "sha512-+m085WKIGkf6wyw4vT85FFXl9j3U35u+LFFVwmLqfPbolnQAtoX24cowXz+vseW4BWKyx6Lamb+Zz+jl69zn6g==", "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-rest-pipeline": "^1.2.0", - "@azure/core-tracing": "^1.0.0", - "debug": "^4.1.1", + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.7.1", + "@azure/core-rest-pipeline": "^1.15.1", + "@azure/core-tracing": "^1.1.1", + "@azure/core-util": "^1.8.1", "fast-json-stable-stringify": "^2.1.0", - "jsbi": "^3.1.3", - "node-abort-controller": "^3.0.0", - "priorityqueuejs": "^1.0.0", - "semaphore": "^1.0.5", - "tslib": "^2.2.0", - "universal-user-agent": "^6.0.0", - "uuid": "^8.3.0" + "jsbi": "^4.3.0", + "priorityqueuejs": "^2.0.0", + "semaphore": "^1.1.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "requires": { + "tslib": "^2.6.2" + } + } } }, "@azure/identity": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.0.1.tgz", - "integrity": "sha512-yRdgF03SFLqUMZZ1gKWt0cs0fvrDIkq2bJ6Oidqcoo5uM85YMBnXWMzYKK30XqIT76lkFyAaoAAy5knXhrG4Lw==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.4.1.tgz", + "integrity": "sha512-DwnG4cKFEM7S3T+9u05NstXU/HN0dk45kPOinUyNKsn5VWwpXd9sbPKEg6kgJzGbm1lMuhx9o31PVbCtM5sfBA==", "requires": { "@azure/abort-controller": "^1.0.0", "@azure/core-auth": "^1.5.0", - "@azure/core-client": "^1.4.0", + "@azure/core-client": "^1.9.2", "@azure/core-rest-pipeline": "^1.1.0", "@azure/core-tracing": "^1.0.0", "@azure/core-util": "^1.3.0", "@azure/logger": "^1.0.0", - "@azure/msal-browser": "^3.5.0", - "@azure/msal-node": "^2.5.1", + "@azure/msal-browser": "^3.14.0", + "@azure/msal-node": "^2.9.2", "events": "^3.0.0", "jws": "^4.0.0", "open": "^8.0.0", @@ -6189,24 +6263,45 @@ } }, "@azure/msal-browser": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.10.0.tgz", - "integrity": "sha512-mnmi8dCXVNZI+AGRq0jKQ3YiodlIC4W9npr6FCB9WN6NQT+6rq+cIlxgUb//BjLyzKsnYo+i4LROGeMyU+6v1A==", +<<<<<<< HEAD + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.21.0.tgz", + "integrity": "sha512-BAwcFsVvOrYzKuUZHhFuvRykUmQGq6lDxst2qGnjxnpNZc3d/tnVPcmhgvUdeKl28VSE0ltgBzT3HkdpDtz9rg==", + "requires": { + "@azure/msal-common": "14.14.1" + } + }, + "@azure/msal-common": { + "version": "14.14.1", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.14.1.tgz", + "integrity": "sha512-2Q3tqNz/PZLfSr8BvcHZVpRRfSn4MjGSqjj9J+HlBsmbf1Uu4P0WeXnemjTJwwx9KrmplsrN3UkZ/LPOR720rw==" + }, + "@azure/msal-node": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.13.0.tgz", + "integrity": "sha512-DhP97ycs7qlCVzzzWGzJiwAFyFj5okno74E4FUZ61oCLfKh4IxA1kxirqzrWuYZWpBe9HVPL6GA4NvmlEOBN5Q==", "requires": { - "@azure/msal-common": "14.7.1" + "@azure/msal-common": "14.14.1", +======= + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.23.0.tgz", + "integrity": "sha512-+QgdMvaeEpdtgRTD7AHHq9aw8uga7mXVHV1KshO1RQ2uI5B55xJ4aEpGlg/ga3H+0arEVcRfT4ZVmX7QLXiCVw==", + "requires": { + "@azure/msal-common": "14.14.2" } }, "@azure/msal-common": { - "version": "14.7.1", - "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.7.1.tgz", - "integrity": "sha512-v96btzjM7KrAu4NSEdOkhQSTGOuNUIIsUdB8wlyB9cdgl5KqEKnTonHUZ8+khvZ6Ap542FCErbnTyDWl8lZ2rA==" + "version": "14.14.2", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.14.2.tgz", + "integrity": "sha512-XV0P5kSNwDwCA/SjIxTe9mEAsKB0NqGNSuaVrkCCE2lAyBr/D6YtD80Vkdp4tjWnPFwjzkwldjr1xU/facOJog==" }, "@azure/msal-node": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.6.4.tgz", - "integrity": "sha512-nNvEPx009/80UATCToF+29NZYocn01uKrB91xtFr7bSqkqO1PuQGXRyYwryWRztUrYZ1YsSbw9A+LmwOhpVvcg==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.13.1.tgz", + "integrity": "sha512-sijfzPNorKt6+9g1/miHwhj6Iapff4mPQx1azmmZExgzUROqWTM1o3ACyxDja0g47VpowFy/sxTM/WsuCyXTiw==", "requires": { - "@azure/msal-common": "14.7.1", + "@azure/msal-common": "14.14.2", +>>>>>>> 0314eec... Fix NDC tests (#40) "jsonwebtoken": "^9.0.0", "uuid": "^8.3.0" } @@ -6640,9 +6735,9 @@ } }, "@hasura/ndc-sdk-typescript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@hasura/ndc-sdk-typescript/-/ndc-sdk-typescript-6.0.0.tgz", - "integrity": "sha512-iLC7IAh2rsW7iyt6swLyOpk0zL32d5LeGN+KSJNJEO6n8eXKsjQpJZBsqKEYOyGcfSlbNqTC1qsobbtwe7Bjyw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@hasura/ndc-sdk-typescript/-/ndc-sdk-typescript-6.1.0.tgz", + "integrity": "sha512-kW+DgohuVzbYuOBp9fqTz0jzdZVlPfsUMdT3HKcXxUlUCvHHuTHffFTxW8TvR/JGk8qGYzA9rbnKelkFQOXf/A==", "requires": { "@json-schema-tools/meta-schema": "^1.7.0", "@opentelemetry/api": "^1.8.0", @@ -7464,11 +7559,6 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" - }, "@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -7504,6 +7594,16 @@ "@types/chai": "*" } }, + "@types/fs-extra": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", + "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", + "dev": true, + "requires": { + "@types/jsonfile": "*", + "@types/node": "*" + } + }, "@types/json-pointer": { "version": "1.0.34", "resolved": "https://registry.npmjs.org/@types/json-pointer/-/json-pointer-1.0.34.tgz", @@ -7516,6 +7616,15 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "@types/jsonfile": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", + "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/jsonpath": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/@types/jsonpath/-/jsonpath-0.2.4.tgz", @@ -7582,11 +7691,11 @@ "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==" }, "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "requires": { - "debug": "4" + "debug": "^4.3.4" } }, "aggregate-error": { @@ -7727,12 +7836,12 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "browser-or-node": { @@ -8177,9 +8286,9 @@ } }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "requires": { "to-regex-range": "^5.0.1" @@ -8243,6 +8352,17 @@ "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", "dev": true }, + "fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -8360,21 +8480,20 @@ "dev": true }, "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "agent-base": "^7.1.0", + "debug": "^4.3.4" } }, "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "requires": { - "agent-base": "6", + "agent-base": "^7.0.2", "debug": "4" } }, @@ -8711,9 +8830,9 @@ } }, "jsbi": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.2.5.tgz", - "integrity": "sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ==" + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-4.3.0.tgz", + "integrity": "sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g==" }, "jsesc": { "version": "2.5.2", @@ -8740,6 +8859,16 @@ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, "jsonwebtoken": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", @@ -9027,11 +9156,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "node-abort-controller": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" - }, "node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -9537,9 +9661,9 @@ "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" }, "priorityqueuejs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-1.0.0.tgz", - "integrity": "sha512-lg++21mreCEOuGWTbO5DnJKAdxfjrdN0S9ysoW9SzdSJvbkWpkaDdpG/cdsPCsEnoLUwmd9m3WcZhngW7yKA2g==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-2.0.0.tgz", + "integrity": "sha512-19BMarhgpq3x4ccvVi8k2QpJZcymo/iFUcrhPd4V96kYGovOdTsWwy7fxChYi4QY+m2EnGBWSX9Buakz+tWNQQ==" }, "process": { "version": "0.11.10", @@ -10279,10 +10403,11 @@ } } }, - "universal-user-agent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", - "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==" + "universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true }, "update-browserslist-db": { "version": "1.0.13", diff --git a/package.json b/package.json index 8241a92..f85529b 100644 --- a/package.json +++ b/package.json @@ -7,10 +7,12 @@ }, "scripts": { "test": "mocha", + "ndc-test": "node script/test-setup.js", "build": "rimraf ./build && tsc", "start": "npm run build && ts-node ./src/index.ts", "install-bin": "tsc && npm install -g", - "cli": "ts-node ./src/cli/index.ts" + "cli": "ts-node ./src/cli/index.ts", + "runSql": "ts-node ./src/runSql.ts" }, "author": "Karthikeyan Chinnakonda", "license": "ISC", @@ -18,20 +20,22 @@ "@apidevtools/json-schema-ref-parser": "^11.5.4", "@types/chai": "^4.3.11", "@types/chai-as-promised": "^7.1.8", + "@types/fs-extra": "^11.0.4", "@types/json-pointer": "^1.0.34", "@types/jsonpath": "^0.2.4", "@types/mocha": "^10.0.6", "@types/node": "^20.11.17", "chai-as-promised": "^7.1.1", "commander": "^11.0.0", + "fs-extra": "^11.2.0", "mocha": "^10.3.0", "nodemon": "^3.1.0", "nyc": "^15.1.0", "rimraf": "^5.0.7" }, "dependencies": { - "@hasura/ndc-sdk-typescript": "^6.0.0", - "@azure/cosmos": "^4.0.0", + "@hasura/ndc-sdk-typescript": "^6.1.0", + "@azure/cosmos": "^4.1.0", "@azure/identity": "^4.0.1", "dotenv": "^16.4.5", "quicktype-core": "^23.0.104", diff --git a/script/data/data.json b/script/data/data.json index f3d21b5..7b453a2 100644 --- a/script/data/data.json +++ b/script/data/data.json @@ -8,21 +8,104 @@ "firstname": "Moungi", "surname": "Bawendi", "motivation": "\"for the discovery and synthesis of quantum dots\"", - "share": "3" + "share": "3", + "birth": { + "year": 1996, + "country": { + "city": "Los Angeles", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2009, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2012, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Turing Award", + "year": 2004, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "1030", "firstname": "Louis", "surname": "Brus", "motivation": "\"for the discovery and synthesis of quantum dots\"", - "share": "3" + "share": "3", + "birth": { + "year": 1973, + "country": { + "city": "Sydney", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2020, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "1031", "firstname": "Aleksey", "surname": "Yekimov", "motivation": "\"for the discovery and synthesis of quantum dots\"", - "share": "3" + "share": "3", + "birth": { + "year": 1967, + "country": { + "city": "Sydney", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2007, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2015, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2016, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 1 @@ -35,8 +118,41 @@ "id": "1034", "firstname": "Claudia", "surname": "Goldin", - "motivation": "\"for having advanced our understanding of women’s labour market outcomes\"", - "share": "1" + "motivation": "\"for having advanced our understanding of women\u2019s labour market outcomes\"", + "share": "1", + "birth": { + "year": 1957, + "country": { + "city": "Sao Paulo", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2023, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2014, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2003, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 2 @@ -50,7 +166,24 @@ "firstname": "Jon", "surname": "Fosse", "motivation": "\"for his innovative plays and prose which give voice to the unsayable\"", - "share": "1" + "share": "1", + "birth": { + "year": 1977, + "country": { + "city": "Sydney", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2010, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 3 @@ -64,7 +197,24 @@ "firstname": "Narges", "surname": "Mohammadi", "motivation": "\"for her fight against the oppression of women in Iran and her fight to promote human rights and freedom for all\"", - "share": "1" + "share": "1", + "birth": { + "year": 1986, + "country": { + "city": "Shanghai", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2008, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 4 @@ -78,21 +228,96 @@ "firstname": "Pierre", "surname": "Agostini", "motivation": "\"for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter\"", - "share": "3" + "share": "3", + "birth": { + "year": 1976, + "country": { + "city": "Los Angeles", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2003, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Fields Medal", + "year": 2007, + "details": { + "category": "computer science", + "organization": "Nobel Committee" + } + } + ] }, { "id": "1027", "firstname": "Ferenc", "surname": "Krausz", "motivation": "\"for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter\"", - "share": "3" + "share": "3", + "birth": { + "year": 1955, + "country": { + "city": "Berlin", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2016, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Turing Award", + "year": 2014, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2006, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "1028", "firstname": "Anne", - "surname": "L’Huillier", + "surname": "L\u2019Huillier", "motivation": "\"for experimental methods that generate attosecond pulses of light for the study of electron dynamics in matter\"", - "share": "3" + "share": "3", + "birth": { + "year": 1966, + "country": { + "city": "Los Angeles", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2023, + "details": { + "category": "computer science", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 5 @@ -104,16 +329,74 @@ { "id": "1024", "firstname": "Katalin", - "surname": "Karikó", + "surname": "Karik\u00f3", "motivation": "\"for their discoveries concerning nucleoside base modifications that enabled the development of effective mRNA vaccines against COVID-19\"", - "share": "2" + "share": "2", + "birth": { + "year": 2014, + "country": { + "city": "London", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2017, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2012, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "1025", "firstname": "Drew", "surname": "Weissman", "motivation": "\"for their discoveries concerning nucleoside base modifications that enabled the development of effective mRNA vaccines against COVID-19\"", - "share": "2" + "share": "2", + "birth": { + "year": 1989, + "country": { + "city": "Los Angeles", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2007, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2010, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2011, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 6 @@ -127,21 +410,112 @@ "firstname": "Carolyn", "surname": "Bertozzi", "motivation": "\"for the development of click chemistry and bioorthogonal chemistry\"", - "share": "3" + "share": "3", + "birth": { + "year": 1951, + "country": { + "city": "London", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2020, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Turing Award", + "year": 2023, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + } + ] }, { "id": "1016", "firstname": "Morten", "surname": "Meldal", "motivation": "\"for the development of click chemistry and bioorthogonal chemistry\"", - "share": "3" + "share": "3", + "birth": { + "year": 1982, + "country": { + "city": "Sydney", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2004, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2022, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2014, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + } + ] }, { "id": "743", "firstname": "Barry", "surname": "Sharpless", "motivation": "\"for the development of click chemistry and bioorthogonal chemistry\"", - "share": "3" + "share": "3", + "birth": { + "year": 1971, + "country": { + "city": "London", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2005, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Turing Award", + "year": 2005, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2001, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 7 @@ -155,21 +529,88 @@ "firstname": "Ben", "surname": "Bernanke", "motivation": "\"for research on banks and financial crises\"", - "share": "3" + "share": "3", + "birth": { + "year": 1994, + "country": { + "city": "Berlin", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2014, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2018, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "1022", "firstname": "Douglas", "surname": "Diamond", "motivation": "\"for research on banks and financial crises\"", - "share": "3" + "share": "3", + "birth": { + "year": 2006, + "country": { + "city": "Shanghai", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2009, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2016, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + } + ] }, { "id": "1023", "firstname": "Philip", "surname": "Dybvig", "motivation": "\"for research on banks and financial crises\"", - "share": "3" + "share": "3", + "birth": { + "year": 2006, + "country": { + "city": "New York", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2012, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 8 @@ -183,7 +624,32 @@ "firstname": "Annie", "surname": "Ernaux", "motivation": "\"for the courage and clinical acuity with which she uncovers the roots, estrangements and collective restraints of personal memory\"", - "share": "1" + "share": "1", + "birth": { + "year": 1999, + "country": { + "city": "Tokyo", + "state": "Maharashtra" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2003, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Fields Medal", + "year": 2010, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 9 @@ -197,19 +663,94 @@ "firstname": "Ales", "surname": "Bialiatski ", "motivation": "\"The Peace Prize laureates represent civil society in their home countries. They have for many years promoted the right to criticise power and protect the fundamental rights of citizens. They have made an outstanding effort to document war crimes, human right abuses and the abuse of power. Together they demonstrate the significance of civil society for peace and democracy.\"", - "share": "3" + "share": "3", + "birth": { + "year": 1995, + "country": { + "city": "London", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2006, + "details": { + "category": "chemistry", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2005, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + } + ] }, { "id": "1019", "motivation": "\"The Peace Prize laureates represent civil society in their home countries. They have for many years promoted the right to criticise power and protect the fundamental rights of citizens. They have made an outstanding effort to document war crimes, human right abuses and the abuse of power. Together they demonstrate the significance of civil society for peace and democracy.\"", "share": "3", - "firstname": "Memorial" + "firstname": "Memorial", + "birth": { + "year": 2009, + "country": { + "city": "Mumbai", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2000, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2003, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2015, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "1020", "motivation": "\"The Peace Prize laureates represent civil society in their home countries. They have for many years promoted the right to criticise power and protect the fundamental rights of citizens. They have made an outstanding effort to document war crimes, human right abuses and the abuse of power. Together they demonstrate the significance of civil society for peace and democracy.\"", "share": "3", - "firstname": "Center for Civil Liberties" + "firstname": "Center for Civil Liberties", + "birth": { + "year": 1951, + "country": { + "city": "Shanghai", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2019, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 10 @@ -223,21 +764,104 @@ "firstname": "Alain", "surname": "Aspect", "motivation": "\"for experiments with entangled photons, establishing the violation of Bell inequalities and pioneering quantum information science\"", - "share": "3" + "share": "3", + "birth": { + "year": 1981, + "country": { + "city": "London", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2022, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2016, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2001, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "1013", "firstname": "John ", "surname": "Clauser", "motivation": "\"for experiments with entangled photons, establishing the violation of Bell inequalities and pioneering quantum information science\"", - "share": "3" + "share": "3", + "birth": { + "year": 2013, + "country": { + "city": "Sydney", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2000, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2006, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2006, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "1014", "firstname": "Anton", "surname": "Zeilinger", "motivation": "\"for experiments with entangled photons, establishing the violation of Bell inequalities and pioneering quantum information science\"", - "share": "3" + "share": "3", + "birth": { + "year": 1955, + "country": { + "city": "Tokyo", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2003, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 11 @@ -249,9 +873,26 @@ { "id": "1011", "firstname": "Svante", - "surname": "Pääbo", + "surname": "P\u00e4\u00e4bo", "motivation": "\"for his discoveries concerning the genomes of extinct hominins and human evolution\"", - "share": "1" + "share": "1", + "birth": { + "year": 1959, + "country": { + "city": "Shanghai", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2006, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 12 @@ -265,14 +906,64 @@ "firstname": "Benjamin", "surname": "List", "motivation": "\"for the development of asymmetric organocatalysis\"", - "share": "2" + "share": "2", + "birth": { + "year": 1997, + "country": { + "city": "Mumbai", + "state": "Berlin" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2004, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2001, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2016, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] }, { "id": "1003", "firstname": "David", "surname": "MacMillan", "motivation": "\"for the development of asymmetric organocatalysis\"", - "share": "2" + "share": "2", + "birth": { + "year": 1981, + "country": { + "city": "Shanghai", + "state": "Maharashtra" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2001, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 13 @@ -286,21 +977,104 @@ "firstname": "David", "surname": "Card", "motivation": "\"for his empirical contributions to labour economics\"", - "share": "2" + "share": "2", + "birth": { + "year": 1977, + "country": { + "city": "Berlin", + "state": "Maharashtra" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2019, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2006, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "1008", "firstname": "Joshua", "surname": "Angrist", "motivation": "\"for their methodological contributions to the analysis of causal relationships\"", - "share": "4" + "share": "4", + "birth": { + "year": 1953, + "country": { + "city": "Sydney", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2019, + "details": { + "category": "computer science", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2013, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "1009", "firstname": "Guido", "surname": "Imbens", "motivation": "\"for their methodological contributions to the analysis of causal relationships\"", - "share": "4" + "share": "4", + "birth": { + "year": 2010, + "country": { + "city": "Tokyo", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2007, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2008, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2017, + "details": { + "category": "computer science", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 14 @@ -314,7 +1088,32 @@ "firstname": "Abdulrazak", "surname": "Gurnah", "motivation": "\"for his uncompromising and compassionate penetration of the effects of colonialism and the fate of the refugee in the gulf between cultures and continents\"", - "share": "1" + "share": "1", + "birth": { + "year": 2007, + "country": { + "city": "Berlin", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2014, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2002, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 15 @@ -328,14 +1127,56 @@ "firstname": "Maria", "surname": "Ressa", "motivation": "\"for their efforts to safeguard freedom of expression, which is a precondition for democracy and lasting peace\"", - "share": "2" + "share": "2", + "birth": { + "year": 1976, + "country": { + "city": "Berlin", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2017, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "1006", "firstname": "Dmitry", "surname": "Muratov", "motivation": "\"for their efforts to safeguard freedom of expression, which is a precondition for democracy and lasting peace\"", - "share": "2" + "share": "2", + "birth": { + "year": 1980, + "country": { + "city": "Tokyo", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2013, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2006, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 16 @@ -349,22 +1190,89 @@ "id": "999", "firstname": "Syukuro", "surname": "Manabe", - "motivation": "\"for the physical modelling of Earth’s climate, quantifying variability and reliably predicting global warming\"", - "share": "4" + "motivation": "\"for the physical modelling of Earth\u2019s climate, quantifying variability and reliably predicting global warming\"", + "share": "4", + "birth": { + "year": 1986, + "country": { + "city": "New York", + "state": "Maharashtra" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2001, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2016, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + } + ] }, { "id": "1000", "firstname": "Klaus", "surname": "Hasselmann", - "motivation": "\"for the physical modelling of Earth’s climate, quantifying variability and reliably predicting global warming\"", - "share": "4" + "motivation": "\"for the physical modelling of Earth\u2019s climate, quantifying variability and reliably predicting global warming\"", + "share": "4", + "birth": { + "year": 1966, + "country": { + "city": "Tokyo", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2019, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Turing Award", + "year": 2005, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "1001", "firstname": "Giorgio", "surname": "Parisi", "motivation": "\"for the discovery of the interplay of disorder and fluctuations in physical systems from atomic to planetary scales\"", - "share": "2" + "share": "2", + "birth": { + "year": 1956, + "country": { + "city": "Shanghai", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2010, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 17 @@ -378,14 +1286,72 @@ "firstname": "David", "surname": "Julius", "motivation": "\"for their discoveries of receptors for temperature and touch\"", - "share": "2" + "share": "2", + "birth": { + "year": 1993, + "country": { + "city": "Berlin", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2022, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2010, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2007, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + } + ] }, { "id": "998", "firstname": "Ardem", "surname": "Patapoutian", "motivation": "\"for their discoveries of receptors for temperature and touch\"", - "share": "2" + "share": "2", + "birth": { + "year": 2002, + "country": { + "city": "Berlin", + "state": "Berlin" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2006, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2021, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 18 @@ -399,14 +1365,64 @@ "firstname": "Emmanuelle", "surname": "Charpentier", "motivation": "\"for the development of a method for genome editing\"", - "share": "2" + "share": "2", + "birth": { + "year": 1977, + "country": { + "city": "Sydney", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2016, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "992", "firstname": "Jennifer A.", "surname": "Doudna", "motivation": "\"for the development of a method for genome editing\"", - "share": "2" + "share": "2", + "birth": { + "year": 2010, + "country": { + "city": "New York", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2000, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2005, + "details": { + "category": "computer science", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2005, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + } + ] } ], "prize_id": 19 @@ -420,14 +1436,56 @@ "firstname": "Paul", "surname": "Milgrom", "motivation": "\"for improvements to auction theory and inventions of new auction formats\"", - "share": "2" + "share": "2", + "birth": { + "year": 1968, + "country": { + "city": "Sao Paulo", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2003, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Fields Medal", + "year": 2022, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "996", "firstname": "Robert", "surname": "Wilson", "motivation": "\"for improvements to auction theory and inventions of new auction formats\"", - "share": "2" + "share": "2", + "birth": { + "year": 1952, + "country": { + "city": "London", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2000, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 20 @@ -439,9 +1497,42 @@ { "id": "993", "firstname": "Louise", - "surname": "Glück", + "surname": "Gl\u00fcck", "motivation": "\"for her unmistakable poetic voice that with austere beauty makes individual existence universal\"", - "share": "1" + "share": "1", + "birth": { + "year": 1999, + "country": { + "city": "London", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2011, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2007, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Fields Medal", + "year": 2005, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + } + ] } ], "prize_id": 21 @@ -454,7 +1545,32 @@ "id": "994", "motivation": "\"for its efforts to combat hunger, for its contribution to bettering conditions for peace in conflict-affected areas and for acting as a driving force in efforts to prevent the use of hunger as a weapon of war and conflict\"", "share": "1", - "firstname": "World Food Programme" + "firstname": "World Food Programme", + "birth": { + "year": 1983, + "country": { + "city": "Mumbai", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2000, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2022, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 22 @@ -468,21 +1584,104 @@ "firstname": "Roger", "surname": "Penrose", "motivation": "\"for the discovery that black hole formation is a robust prediction of the general theory of relativity\"", - "share": "2" + "share": "2", + "birth": { + "year": 2011, + "country": { + "city": "Sao Paulo", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2001, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + } + ] }, { "id": "989", "firstname": "Reinhard", "surname": "Genzel", "motivation": "\"for the discovery of a supermassive compact object at the centre of our galaxy\"", - "share": "4" + "share": "4", + "birth": { + "year": 1992, + "country": { + "city": "Tokyo", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2020, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2006, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2012, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] }, { "id": "990", "firstname": "Andrea", "surname": "Ghez", "motivation": "\"for the discovery of a supermassive compact object at the centre of our galaxy\"", - "share": "4" + "share": "4", + "birth": { + "year": 2006, + "country": { + "city": "Tokyo", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2007, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2003, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2013, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 23 @@ -496,21 +1695,80 @@ "firstname": "Harvey", "surname": "Alter", "motivation": "\"for the discovery of Hepatitis C virus\"", - "share": "3" + "share": "3", + "birth": { + "year": 2019, + "country": { + "city": "Tokyo", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2014, + "details": { + "category": "computer science", + "organization": "Nobel Committee" + } + } + ] }, { "id": "986", "firstname": "Michael", "surname": "Houghton", "motivation": "\"for the discovery of Hepatitis C virus\"", - "share": "3" + "share": "3", + "birth": { + "year": 1966, + "country": { + "city": "Sao Paulo", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2005, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2009, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "987", "firstname": "Charles", "surname": "Rice", "motivation": "\"for the discovery of Hepatitis C virus\"", - "share": "3" + "share": "3", + "birth": { + "year": 2018, + "country": { + "city": "London", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2009, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 24 @@ -524,21 +1782,88 @@ "firstname": "John", "surname": "Goodenough", "motivation": "\"for the development of lithium-ion batteries\"", - "share": "3" + "share": "3", + "birth": { + "year": 2023, + "country": { + "city": "Los Angeles", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2017, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2005, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2012, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "977", "firstname": "M. Stanley", "surname": "Whittingham", "motivation": "\"for the development of lithium-ion batteries\"", - "share": "3" + "share": "3", + "birth": { + "year": 1987, + "country": { + "city": "Berlin", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2004, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + } + ] }, { "id": "978", "firstname": "Akira", "surname": "Yoshino", "motivation": "\"for the development of lithium-ion batteries\"", - "share": "3" + "share": "3", + "birth": { + "year": 1950, + "country": { + "city": "Mumbai", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2000, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 25 @@ -552,21 +1877,80 @@ "firstname": "Abhijit", "surname": "Banerjee", "motivation": "\"for their experimental approach to alleviating global poverty\"", - "share": "3" + "share": "3", + "birth": { + "year": 2006, + "country": { + "city": "Tokyo", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2019, + "details": { + "category": "chemistry", + "organization": "Fields Medal Committee" + } + } + ] }, { "id": "983", "firstname": "Esther", "surname": "Duflo", "motivation": "\"for their experimental approach to alleviating global poverty\"", - "share": "3" + "share": "3", + "birth": { + "year": 2006, + "country": { + "city": "Sydney", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2016, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + } + ] }, { "id": "984", "firstname": "Michael", "surname": "Kremer", "motivation": "\"for their experimental approach to alleviating global poverty\"", - "share": "3" + "share": "3", + "birth": { + "year": 1951, + "country": { + "city": "Shanghai", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2012, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2007, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + } + ] } ], "prize_id": 26 @@ -580,7 +1964,32 @@ "firstname": "Peter", "surname": "Handke", "motivation": "\"for an influential work that with linguistic ingenuity has explored the periphery and the specificity of human experience\"", - "share": "1" + "share": "1", + "birth": { + "year": 1991, + "country": { + "city": "New York", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2019, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2012, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 27 @@ -594,7 +2003,24 @@ "firstname": "Abiy", "surname": "Ahmed Ali", "motivation": "\"for his efforts to achieve peace and international cooperation, and in particular for his decisive initiative to resolve the border conflict with neighbouring Eritrea\"", - "share": "1" + "share": "1", + "birth": { + "year": 1983, + "country": { + "city": "Los Angeles", + "state": "Maharashtra" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2011, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + } + ] } ], "prize_id": 28 @@ -602,28 +2028,103 @@ { "year": 2019, "category": "physics", - "overallMotivation": "\"for contributions to our understanding of the evolution of the universe and Earth’s place in the cosmos\"", + "overallMotivation": "\"for contributions to our understanding of the evolution of the universe and Earth\u2019s place in the cosmos\"", "laureates": [ { "id": "973", "firstname": "James", "surname": "Peebles", "motivation": "\"for theoretical discoveries in physical cosmology\"", - "share": "2" + "share": "2", + "birth": { + "year": 1974, + "country": { + "city": "Tokyo", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2023, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2005, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2009, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "974", "firstname": "Michel", "surname": "Mayor", "motivation": "\"for the discovery of an exoplanet orbiting a solar-type star\"", - "share": "4" + "share": "4", + "birth": { + "year": 2010, + "country": { + "city": "Shanghai", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2015, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2019, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "975", "firstname": "Didier", "surname": "Queloz", "motivation": "\"for the discovery of an exoplanet orbiting a solar-type star\"", - "share": "4" + "share": "4", + "birth": { + "year": 2020, + "country": { + "city": "Los Angeles", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2001, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + } + ] } ], "prize_id": 29 @@ -637,21 +2138,96 @@ "firstname": "William", "surname": "Kaelin", "motivation": "\"for their discoveries of how cells sense and adapt to oxygen availability\"", - "share": "3" + "share": "3", + "birth": { + "year": 1983, + "country": { + "city": "Tokyo", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2006, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2020, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2005, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "971", "firstname": "Peter", "surname": "Ratcliffe", "motivation": "\"for their discoveries of how cells sense and adapt to oxygen availability\"", - "share": "3" + "share": "3", + "birth": { + "year": 2003, + "country": { + "city": "Paris", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2004, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2017, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + } + ] }, { "id": "972", "firstname": "Gregg", "surname": "Semenza", "motivation": "\"for their discoveries of how cells sense and adapt to oxygen availability\"", - "share": "3" + "share": "3", + "birth": { + "year": 1979, + "country": { + "city": "Mumbai", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2017, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 30 @@ -665,21 +2241,96 @@ "firstname": "Frances H.", "surname": "Arnold", "motivation": "\"for the directed evolution of enzymes\"", - "share": "2" + "share": "2", + "birth": { + "year": 1977, + "country": { + "city": "Paris", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2019, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2014, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Fields Medal", + "year": 2007, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "964", "firstname": "George P.", "surname": "Smith", "motivation": "\"for the phage display of peptides and antibodies\"", - "share": "4" + "share": "4", + "birth": { + "year": 1982, + "country": { + "city": "Los Angeles", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2014, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + } + ] }, { "id": "965", "firstname": "Sir Gregory P.", "surname": "Winter", "motivation": "\"for the phage display of peptides and antibodies\"", - "share": "4" + "share": "4", + "birth": { + "year": 2022, + "country": { + "city": "Sydney", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2016, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2020, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 31 @@ -693,14 +2344,56 @@ "firstname": "William D.", "surname": "Nordhaus", "motivation": "\"for integrating climate change into long-run macroeconomic analysis\"", - "share": "2" + "share": "2", + "birth": { + "year": 1996, + "country": { + "city": "London", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2003, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2021, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + } + ] }, { "id": "969", "firstname": "Paul M.", "surname": "Romer", "motivation": "\"for integrating technological innovations into long-run macroeconomic analysis\"", - "share": "2" + "share": "2", + "birth": { + "year": 2018, + "country": { + "city": "Tokyo", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2023, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 32 @@ -714,7 +2407,24 @@ "firstname": "Olga", "surname": "Tokarczuk", "motivation": "\"for a narrative imagination that with encyclopedic passion represents the crossing of boundaries as a form of life\"", - "share": "1" + "share": "1", + "birth": { + "year": 1972, + "country": { + "city": "Tokyo", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2007, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 33 @@ -728,14 +2438,64 @@ "firstname": "Denis", "surname": "Mukwege", "motivation": "\"for their efforts to end the use of sexual violence as a weapon of war and armed conflict\"", - "share": "2" + "share": "2", + "birth": { + "year": 1992, + "country": { + "city": "Mumbai", + "state": "Berlin" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2013, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2016, + "details": { + "category": "computer science", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2007, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "967", "firstname": "Nadia", "surname": "Murad", "motivation": "\"for their efforts to end the use of sexual violence as a weapon of war and armed conflict\"", - "share": "2" + "share": "2", + "birth": { + "year": 1977, + "country": { + "city": "Shanghai", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2013, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 34 @@ -750,21 +2510,88 @@ "firstname": "Arthur", "surname": "Ashkin", "motivation": "\"for the optical tweezers and their application to biological systems\"", - "share": "2" + "share": "2", + "birth": { + "year": 1973, + "country": { + "city": "Berlin", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2021, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Fields Medal", + "year": 2009, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] }, { "id": "961", - "firstname": "Gérard", + "firstname": "G\u00e9rard", "surname": "Mourou", "motivation": "\"for their method of generating high-intensity, ultra-short optical pulses\"", - "share": "4" + "share": "4", + "birth": { + "year": 1960, + "country": { + "city": "Los Angeles", + "state": "Maharashtra" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2006, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2001, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "962", "firstname": "Donna", "surname": "Strickland", "motivation": "\"for their method of generating high-intensity, ultra-short optical pulses\"", - "share": "4" + "share": "4", + "birth": { + "year": 1973, + "country": { + "city": "Sao Paulo", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2021, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 35 @@ -778,14 +2605,72 @@ "firstname": "James P.", "surname": "Allison", "motivation": "\"for their discovery of cancer therapy by inhibition of negative immune regulation\"", - "share": "2" + "share": "2", + "birth": { + "year": 1959, + "country": { + "city": "Berlin", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2014, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2003, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + } + ] }, { "id": "959", "firstname": "Tasuku", "surname": "Honjo", "motivation": "\"for their discovery of cancer therapy by inhibition of negative immune regulation\"", - "share": "2" + "share": "2", + "birth": { + "year": 1994, + "country": { + "city": "Tokyo", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2013, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2019, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2003, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + } + ] } ], "prize_id": 36 @@ -799,21 +2684,96 @@ "firstname": "Jacques", "surname": "Dubochet", "motivation": "\"for developing cryo-electron microscopy for the high-resolution structure determination of biomolecules in solution\"", - "share": "3" + "share": "3", + "birth": { + "year": 1963, + "country": { + "city": "Berlin", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2018, + "details": { + "category": "chemistry", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2016, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "945", "firstname": "Joachim", "surname": "Frank", "motivation": "\"for developing cryo-electron microscopy for the high-resolution structure determination of biomolecules in solution\"", - "share": "3" + "share": "3", + "birth": { + "year": 1976, + "country": { + "city": "Mumbai", + "state": "Berlin" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2023, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Turing Award", + "year": 2020, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + } + ] }, { "id": "946", "firstname": "Richard", "surname": "Henderson", "motivation": "\"for developing cryo-electron microscopy for the high-resolution structure determination of biomolecules in solution\"", - "share": "3" + "share": "3", + "birth": { + "year": 1981, + "country": { + "city": "Mumbai", + "state": "Berlin" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2020, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2007, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 37 @@ -827,7 +2787,24 @@ "firstname": "Richard H.", "surname": "Thaler", "motivation": "\"for his contributions to behavioural economics\"", - "share": "1" + "share": "1", + "birth": { + "year": 1956, + "country": { + "city": "Berlin", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2021, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 38 @@ -841,7 +2818,32 @@ "firstname": "Kazuo", "surname": "Ishiguro", "motivation": "\"who, in novels of great emotional force, has uncovered the abyss beneath our illusory sense of connection with the world\"", - "share": "1" + "share": "1", + "birth": { + "year": 1952, + "country": { + "city": "Mumbai", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2011, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2016, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + } + ] } ], "prize_id": 39 @@ -854,7 +2856,32 @@ "id": "948", "motivation": "\"for its work to draw attention to the catastrophic humanitarian consequences of any use of nuclear weapons and for its ground-breaking efforts to achieve a treaty-based prohibition of such weapons\"", "share": "1", - "firstname": "International Campaign to Abolish Nuclear Weapons" + "firstname": "International Campaign to Abolish Nuclear Weapons", + "birth": { + "year": 1974, + "country": { + "city": "Mumbai", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2023, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2003, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 40 @@ -868,21 +2895,104 @@ "firstname": "Rainer", "surname": "Weiss", "motivation": "\"for decisive contributions to the LIGO detector and the observation of gravitational waves\"", - "share": "2" + "share": "2", + "birth": { + "year": 1952, + "country": { + "city": "Berlin", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2005, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2014, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "942", "firstname": "Barry C.", "surname": "Barish", "motivation": "\"for decisive contributions to the LIGO detector and the observation of gravitational waves\"", - "share": "4" + "share": "4", + "birth": { + "year": 1974, + "country": { + "city": "Paris", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2006, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2022, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2014, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "943", "firstname": "Kip S.", "surname": "Thorne", "motivation": "\"for decisive contributions to the LIGO detector and the observation of gravitational waves\"", - "share": "4" + "share": "4", + "birth": { + "year": 1975, + "country": { + "city": "Berlin", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2016, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2017, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 41 @@ -896,21 +3006,96 @@ "firstname": "Jeffrey C.", "surname": "Hall", "motivation": "\"for their discoveries of molecular mechanisms controlling the circadian rhythm\"", - "share": "3" + "share": "3", + "birth": { + "year": 1979, + "country": { + "city": "Sao Paulo", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2021, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2013, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] }, { "id": "939", "firstname": "Michael", "surname": "Rosbash", "motivation": "\"for their discoveries of molecular mechanisms controlling the circadian rhythm\"", - "share": "3" + "share": "3", + "birth": { + "year": 2001, + "country": { + "city": "Sydney", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2023, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "940", "firstname": "Michael W.", "surname": "Young", "motivation": "\"for their discoveries of molecular mechanisms controlling the circadian rhythm\"", - "share": "3" + "share": "3", + "birth": { + "year": 2008, + "country": { + "city": "Sydney", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2009, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2013, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2000, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 42 @@ -924,21 +3109,96 @@ "firstname": "Jean-Pierre", "surname": "Sauvage", "motivation": "\"for the design and synthesis of molecular machines\"", - "share": "3" + "share": "3", + "birth": { + "year": 1977, + "country": { + "city": "Mumbai", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2020, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2012, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + } + ] }, { "id": "932", "firstname": "Sir J. Fraser", "surname": "Stoddart", "motivation": "\"for the design and synthesis of molecular machines\"", - "share": "3" + "share": "3", + "birth": { + "year": 1992, + "country": { + "city": "Tokyo", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2009, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Turing Award", + "year": 2014, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Turing Award", + "year": 2016, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "933", "firstname": "Bernard L.", "surname": "Feringa", "motivation": "\"for the design and synthesis of molecular machines\"", - "share": "3" + "share": "3", + "birth": { + "year": 1985, + "country": { + "city": "New York", + "state": "Maharashtra" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2009, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + } + ] } ], "prize_id": 43 @@ -952,14 +3212,48 @@ "firstname": "Oliver", "surname": "Hart", "motivation": "\"for their contributions to contract theory\"", - "share": "2" + "share": "2", + "birth": { + "year": 1989, + "country": { + "city": "Los Angeles", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2014, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "936", "firstname": "Bengt", - "surname": "Holmström", + "surname": "Holmstr\u00f6m", "motivation": "\"for their contributions to contract theory\"", - "share": "2" + "share": "2", + "birth": { + "year": 1994, + "country": { + "city": "Sydney", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2016, + "details": { + "category": "chemistry", + "organization": "Fields Medal Committee" + } + } + ] } ], "prize_id": 44 @@ -973,7 +3267,32 @@ "firstname": "Bob", "surname": "Dylan", "motivation": "\"for having created new poetic expressions within the great American song tradition\"", - "share": "1" + "share": "1", + "birth": { + "year": 2004, + "country": { + "city": "Mumbai", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2017, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2022, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + } + ] } ], "prize_id": 45 @@ -987,7 +3306,32 @@ "firstname": "Juan Manuel", "surname": "Santos", "motivation": "\"for his resolute efforts to bring the country's more than 50-year-long civil war to an end\"", - "share": "1" + "share": "1", + "birth": { + "year": 1995, + "country": { + "city": "Berlin", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2016, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2004, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 46 @@ -1001,21 +3345,88 @@ "firstname": "David J.", "surname": "Thouless", "motivation": "\"for theoretical discoveries of topological phase transitions and topological phases of matter\"", - "share": "2" + "share": "2", + "birth": { + "year": 1968, + "country": { + "city": "Sao Paulo", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2020, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2005, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "929", "firstname": "F. Duncan M.", "surname": "Haldane", "motivation": "\"for theoretical discoveries of topological phase transitions and topological phases of matter\"", - "share": "4" + "share": "4", + "birth": { + "year": 2009, + "country": { + "city": "Sydney", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2008, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2007, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "930", "firstname": "J. Michael", "surname": "Kosterlitz", "motivation": "\"for theoretical discoveries of topological phase transitions and topological phases of matter\"", - "share": "4" + "share": "4", + "birth": { + "year": 1967, + "country": { + "city": "Paris", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2011, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + } + ] } ], "prize_id": 47 @@ -1029,7 +3440,40 @@ "firstname": "Yoshinori", "surname": "Ohsumi", "motivation": "\"for his discoveries of mechanisms for autophagy\"", - "share": "1" + "share": "1", + "birth": { + "year": 1993, + "country": { + "city": "Shanghai", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2017, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2001, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2007, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + } + ] } ], "prize_id": 48 @@ -1043,21 +3487,104 @@ "firstname": "Tomas", "surname": "Lindahl", "motivation": "\"for mechanistic studies of DNA repair\"", - "share": "3" + "share": "3", + "birth": { + "year": 2016, + "country": { + "city": "Sydney", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2014, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2006, + "details": { + "category": "computer science", + "organization": "Nobel Committee" + } + } + ] }, { "id": "922", "firstname": "Paul", "surname": "Modrich", "motivation": "\"for mechanistic studies of DNA repair\"", - "share": "3" + "share": "3", + "birth": { + "year": 1956, + "country": { + "city": "Berlin", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2010, + "details": { + "category": "computer science", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2007, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "923", "firstname": "Aziz", "surname": "Sancar", "motivation": "\"for mechanistic studies of DNA repair\"", - "share": "3" + "share": "3", + "birth": { + "year": 1954, + "country": { + "city": "Sao Paulo", + "state": "Berlin" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2000, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2023, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Turing Award", + "year": 2003, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + } + ] } ], "prize_id": 49 @@ -1071,7 +3598,40 @@ "firstname": "Angus", "surname": "Deaton", "motivation": "\"for his analysis of consumption, poverty, and welfare\"", - "share": "1" + "share": "1", + "birth": { + "year": 2000, + "country": { + "city": "Los Angeles", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2014, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2012, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2013, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + } + ] } ], "prize_id": 50 @@ -1085,7 +3645,32 @@ "firstname": "Svetlana", "surname": "Alexievich", "motivation": "\"for her polyphonic writings, a monument to suffering and courage in our time\"", - "share": "1" + "share": "1", + "birth": { + "year": 2011, + "country": { + "city": "Tokyo", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2002, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2021, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 51 @@ -1098,7 +3683,24 @@ "id": "925", "motivation": "\"for its decisive contribution to the building of a pluralistic democracy in Tunisia in the wake of the Jasmine Revolution of 2011\"", "share": "1", - "firstname": "National Dialogue Quartet" + "firstname": "National Dialogue Quartet", + "birth": { + "year": 2010, + "country": { + "city": "Los Angeles", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2010, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 52 @@ -1112,14 +3714,80 @@ "firstname": "Takaaki", "surname": "Kajita", "motivation": "\"for the discovery of neutrino oscillations, which shows that neutrinos have mass\"", - "share": "2" + "share": "2", + "birth": { + "year": 1992, + "country": { + "city": "Sydney", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2013, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Fields Medal", + "year": 2004, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Turing Award", + "year": 2012, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "920", "firstname": "Arthur B.", "surname": "McDonald", "motivation": "\"for the discovery of neutrino oscillations, which shows that neutrinos have mass\"", - "share": "2" + "share": "2", + "birth": { + "year": 1991, + "country": { + "city": "Mumbai", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2020, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2011, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2020, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 53 @@ -1133,21 +3801,80 @@ "firstname": "William C.", "surname": "Campbell", "motivation": "\"for their discoveries concerning a novel therapy against infections caused by roundworm parasites\"", - "share": "4" + "share": "4", + "birth": { + "year": 1988, + "country": { + "city": "Sao Paulo", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2008, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2010, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] }, { "id": "917", "firstname": "Satoshi", - "surname": "Ōmura", + "surname": "\u014cmura", "motivation": "\"for their discoveries concerning a novel therapy against infections caused by roundworm parasites\"", - "share": "4" + "share": "4", + "birth": { + "year": 1976, + "country": { + "city": "Berlin", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2000, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "918", "firstname": "Youyou", "surname": "Tu", "motivation": "\"for her discoveries concerning a novel therapy against Malaria\"", - "share": "2" + "share": "2", + "birth": { + "year": 1991, + "country": { + "city": "Sao Paulo", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2013, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + } + ] } ], "prize_id": 54 @@ -1161,21 +3888,104 @@ "firstname": "Eric", "surname": "Betzig", "motivation": "\"for the development of super-resolved fluorescence microscopy\"", - "share": "3" + "share": "3", + "birth": { + "year": 1989, + "country": { + "city": "Los Angeles", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2002, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2021, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2013, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + } + ] }, { "id": "910", "firstname": "Stefan W.", "surname": "Hell", "motivation": "\"for the development of super-resolved fluorescence microscopy\"", - "share": "3" + "share": "3", + "birth": { + "year": 1954, + "country": { + "city": "Paris", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2017, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "911", "firstname": "William E.", "surname": "Moerner", "motivation": "\"for the development of super-resolved fluorescence microscopy\"", - "share": "3" + "share": "3", + "birth": { + "year": 1967, + "country": { + "city": "Mumbai", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2020, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Fields Medal", + "year": 2011, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2022, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 55 @@ -1189,7 +3999,40 @@ "firstname": "Jean", "surname": "Tirole", "motivation": "\"for his analysis of market power and regulation\"", - "share": "1" + "share": "1", + "birth": { + "year": 1994, + "country": { + "city": "Mumbai", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2013, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2007, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2011, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 56 @@ -1203,7 +4046,32 @@ "firstname": "Patrick", "surname": "Modiano", "motivation": "\"for the art of memory with which he has evoked the most ungraspable human destinies and\r\nuncovered the life-world of the occupation\"", - "share": "1" + "share": "1", + "birth": { + "year": 1982, + "country": { + "city": "Sao Paulo", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2022, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2005, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + } + ] } ], "prize_id": 57 @@ -1217,14 +4085,80 @@ "firstname": "Kailash", "surname": "Satyarthi", "motivation": "\"for their struggle against the suppression of children and young people and for the right of all children to education\"", - "share": "2" + "share": "2", + "birth": { + "year": 1951, + "country": { + "city": "Sao Paulo", + "state": "Maharashtra" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2012, + "details": { + "category": "computer science", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2003, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2000, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "914", "firstname": "Malala", "surname": "Yousafzai", "motivation": "\"for their struggle against the suppression of children and young people and for the right of all children to education\"", - "share": "2" + "share": "2", + "birth": { + "year": 1996, + "country": { + "city": "Mumbai", + "state": "Berlin" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2013, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2020, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2000, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 58 @@ -1238,21 +4172,88 @@ "firstname": "Isamu", "surname": "Akasaki", "motivation": "\"for the invention of efficient blue light-emitting diodes which has enabled bright and energy-saving white light sources\"", - "share": "3" + "share": "3", + "birth": { + "year": 1997, + "country": { + "city": "Berlin", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2002, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "907", "firstname": "Hiroshi", "surname": "Amano", "motivation": "\"for the invention of efficient blue light-emitting diodes which has enabled bright and energy-saving white light sources\"", - "share": "3" + "share": "3", + "birth": { + "year": 2009, + "country": { + "city": "Paris", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2022, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2002, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Turing Award", + "year": 2012, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + } + ] }, { "id": "908", "firstname": "Shuji", "surname": "Nakamura", "motivation": "\"for the invention of efficient blue light-emitting diodes which has enabled bright and energy-saving white light sources\"", - "share": "3" + "share": "3", + "birth": { + "year": 1988, + "country": { + "city": "Mumbai", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2016, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 59 @@ -1266,21 +4267,88 @@ "firstname": "John", "surname": "O'Keefe", "motivation": "\"for their discoveries of cells that constitute a positioning system in the brain\"", - "share": "2" + "share": "2", + "birth": { + "year": 2010, + "country": { + "city": "Shanghai", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2003, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "904", "firstname": "May-Britt", "surname": "Moser", "motivation": "\"for their discoveries of cells that constitute a positioning system in the brain\"", - "share": "4" + "share": "4", + "birth": { + "year": 1991, + "country": { + "city": "New York", + "state": "Berlin" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2022, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2023, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Fields Medal", + "year": 2010, + "details": { + "category": "computer science", + "organization": "Nobel Committee" + } + } + ] }, { "id": "905", "firstname": "Edvard I.", "surname": "Moser", "motivation": "\"for their discoveries of cells that constitute a positioning system in the brain\"", - "share": "4" + "share": "4", + "birth": { + "year": 1966, + "country": { + "city": "New York", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2023, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 60 @@ -1294,21 +4362,96 @@ "firstname": "Martin", "surname": "Karplus", "motivation": "\"for the development of multiscale models for complex chemical systems\"", - "share": "3" + "share": "3", + "birth": { + "year": 1962, + "country": { + "city": "Shanghai", + "state": "Berlin" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2020, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2004, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2004, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] }, { "id": "890", "firstname": "Michael", "surname": "Levitt", "motivation": "\"for the development of multiscale models for complex chemical systems\"", - "share": "3" + "share": "3", + "birth": { + "year": 2007, + "country": { + "city": "Tokyo", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2004, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2001, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + } + ] }, { "id": "891", "firstname": "Arieh", "surname": "Warshel", "motivation": "\"for the development of multiscale models for complex chemical systems\"", - "share": "3" + "share": "3", + "birth": { + "year": 1960, + "country": { + "city": "Los Angeles", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2020, + "details": { + "category": "chemistry", + "organization": "Fields Medal Committee" + } + } + ] } ], "prize_id": 61 @@ -1322,21 +4465,80 @@ "firstname": "Eugene F.", "surname": "Fama", "motivation": "\"for their empirical analysis of asset prices\"", - "share": "3" + "share": "3", + "birth": { + "year": 1993, + "country": { + "city": "London", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2017, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "895", "firstname": "Lars Peter", "surname": "Hansen", "motivation": "\"for their empirical analysis of asset prices\"", - "share": "3" + "share": "3", + "birth": { + "year": 1973, + "country": { + "city": "Paris", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2007, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "896", "firstname": "Robert J.", "surname": "Shiller", "motivation": "\"for their empirical analysis of asset prices\"", - "share": "3" + "share": "3", + "birth": { + "year": 1993, + "country": { + "city": "Shanghai", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2022, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2015, + "details": { + "category": "computer science", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 62 @@ -1350,7 +4552,24 @@ "firstname": "Alice", "surname": "Munro", "motivation": "\"master of the contemporary short story\"", - "share": "1" + "share": "1", + "birth": { + "year": 1965, + "country": { + "city": "Sydney", + "state": "Maharashtra" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2018, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 63 @@ -1363,7 +4582,24 @@ "id": "893", "motivation": "\"for its extensive efforts to eliminate chemical weapons\"", "share": "1", - "firstname": "Organisation for the Prohibition of Chemical Weapons" + "firstname": "Organisation for the Prohibition of Chemical Weapons", + "birth": { + "year": 2009, + "country": { + "city": "London", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2018, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + } + ] } ], "prize_id": 64 @@ -1374,17 +4610,67 @@ "laureates": [ { "id": "887", - "firstname": "François", + "firstname": "Fran\u00e7ois", "surname": "Englert", "motivation": "\"for the theoretical discovery of a mechanism that contributes to our understanding of the origin of mass of subatomic particles, and which recently was confirmed through the discovery of the predicted fundamental particle, by the ATLAS and CMS experiments at CERN's Large Hadron Collider\"", - "share": "2" + "share": "2", + "birth": { + "year": 1984, + "country": { + "city": "New York", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2002, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Fields Medal", + "year": 2023, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2018, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "888", "firstname": "Peter", "surname": "Higgs", "motivation": "\"for the theoretical discovery of a mechanism that contributes to our understanding of the origin of mass of subatomic particles, and which recently was confirmed through the discovery of the predicted fundamental particle, by the ATLAS and CMS experiments at CERN's Large Hadron Collider\"", - "share": "2" + "share": "2", + "birth": { + "year": 2000, + "country": { + "city": "Berlin", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2012, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 65 @@ -1398,21 +4684,80 @@ "firstname": "James E.", "surname": "Rothman", "motivation": "\"for their discoveries of machinery regulating vesicle traffic, a major transport system in our cells\"", - "share": "3" + "share": "3", + "birth": { + "year": 2002, + "country": { + "city": "Paris", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2007, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2006, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "885", "firstname": "Randy W.", "surname": "Schekman", "motivation": "\"for their discoveries of machinery regulating vesicle traffic, a major transport system in our cells\"", - "share": "3" + "share": "3", + "birth": { + "year": 2019, + "country": { + "city": "Paris", + "state": "Maharashtra" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2009, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "886", "firstname": "Thomas C.", - "surname": "Südhof", + "surname": "S\u00fcdhof", "motivation": "\"for their discoveries of machinery regulating vesicle traffic, a major transport system in our cells\"", - "share": "3" + "share": "3", + "birth": { + "year": 1998, + "country": { + "city": "London", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2004, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 66 @@ -1426,14 +4771,72 @@ "firstname": "Robert J.", "surname": "Lefkowitz", "motivation": "\"for studies of G-protein-coupled receptors\"", - "share": "2" + "share": "2", + "birth": { + "year": 1988, + "country": { + "city": "Los Angeles", + "state": "Berlin" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2000, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Fields Medal", + "year": 2002, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2009, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "879", "firstname": "Brian", "surname": "Kobilka", "motivation": "\"for studies of G-protein-coupled receptors\"", - "share": "2" + "share": "2", + "birth": { + "year": 2010, + "country": { + "city": "Berlin", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2020, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2001, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 67 @@ -1447,14 +4850,56 @@ "firstname": "Alvin E.", "surname": "Roth", "motivation": "\"for the theory of stable allocations and the practice of market design\"", - "share": "2" + "share": "2", + "birth": { + "year": 1972, + "country": { + "city": "Mumbai", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2019, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2017, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "883", "firstname": "Lloyd S.", "surname": "Shapley", "motivation": "\"for the theory of stable allocations and the practice of market design\"", - "share": "2" + "share": "2", + "birth": { + "year": 1966, + "country": { + "city": "Los Angeles", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2002, + "details": { + "category": "chemistry", + "organization": "Fields Medal Committee" + } + } + ] } ], "prize_id": 68 @@ -1468,7 +4913,40 @@ "firstname": "Mo", "surname": "Yan", "motivation": "\"who with hallucinatory realism merges folk tales, history and the contemporary\"", - "share": "1" + "share": "1", + "birth": { + "year": 2003, + "country": { + "city": "Mumbai", + "state": "Berlin" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2002, + "details": { + "category": "chemistry", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2022, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2020, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 69 @@ -1481,7 +4959,24 @@ "id": "881", "motivation": "\"for over six decades contributed to the advancement of peace and reconciliation, democracy and human rights in Europe\"", "share": "1", - "firstname": "European Union" + "firstname": "European Union", + "birth": { + "year": 2019, + "country": { + "city": "Sydney", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2008, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + } + ] } ], "prize_id": 70 @@ -1495,14 +4990,64 @@ "firstname": "Serge", "surname": "Haroche", "motivation": "\"for ground-breaking experimental methods that enable measuring and manipulation of individual quantum systems\"", - "share": "2" + "share": "2", + "birth": { + "year": 2015, + "country": { + "city": "Sao Paulo", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2016, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2001, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2003, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "877", "firstname": "David J.", "surname": "Wineland", "motivation": "\"for ground-breaking experimental methods that enable measuring and manipulation of individual quantum systems\"", - "share": "2" + "share": "2", + "birth": { + "year": 2002, + "country": { + "city": "Sao Paulo", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2013, + "details": { + "category": "computer science", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 71 @@ -1516,14 +5061,56 @@ "firstname": "Sir John B.", "surname": "Gurdon", "motivation": "\"for the discovery that mature cells can be reprogrammed to become pluripotent\"", - "share": "2" + "share": "2", + "birth": { + "year": 1982, + "country": { + "city": "Tokyo", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2004, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2004, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + } + ] }, { "id": "875", "firstname": "Shinya", "surname": "Yamanaka", "motivation": "\"for the discovery that mature cells can be reprogrammed to become pluripotent\"", - "share": "2" + "share": "2", + "birth": { + "year": 1971, + "country": { + "city": "Paris", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2001, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 72 @@ -1537,7 +5124,24 @@ "firstname": "Dan", "surname": "Shechtman", "motivation": "\"for the discovery of quasicrystals\"", - "share": "1" + "share": "1", + "birth": { + "year": 1962, + "country": { + "city": "Mumbai", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2014, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 73 @@ -1551,14 +5155,80 @@ "firstname": "Thomas J.", "surname": "Sargent", "motivation": "\"for their empirical research on cause and effect in the macroeconomy\"", - "share": "2" + "share": "2", + "birth": { + "year": 1961, + "country": { + "city": "Los Angeles", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2021, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2006, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2005, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "873", "firstname": "Christopher A.", "surname": "Sims", "motivation": "\"for their empirical research on cause and effect in the macroeconomy\"", - "share": "2" + "share": "2", + "birth": { + "year": 1964, + "country": { + "city": "Berlin", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2003, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2009, + "details": { + "category": "chemistry", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2010, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + } + ] } ], "prize_id": 74 @@ -1570,9 +5240,42 @@ { "id": "868", "firstname": "Tomas", - "surname": "Tranströmer", + "surname": "Transtr\u00f6mer", "motivation": "\"because, through his condensed, translucent images, he gives us fresh access to reality\"", - "share": "1" + "share": "1", + "birth": { + "year": 2014, + "country": { + "city": "Berlin", + "state": "Berlin" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2002, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2006, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2004, + "details": { + "category": "computer science", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 75 @@ -1586,21 +5289,96 @@ "firstname": "Ellen", "surname": "Johnson Sirleaf", "motivation": "\"for their non-violent struggle for the safety of women and for women's rights to full participation in peace-building work\"", - "share": "3" + "share": "3", + "birth": { + "year": 2008, + "country": { + "city": "Los Angeles", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2004, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2022, + "details": { + "category": "chemistry", + "organization": "Fields Medal Committee" + } + } + ] }, { "id": "870", "firstname": "Leymah", "surname": "Gbowee", "motivation": "\"for their non-violent struggle for the safety of women and for women's rights to full participation in peace-building work\"", - "share": "3" + "share": "3", + "birth": { + "year": 2006, + "country": { + "city": "Sao Paulo", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2005, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2003, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Turing Award", + "year": 2002, + "details": { + "category": "computer science", + "organization": "Nobel Committee" + } + } + ] }, { "id": "871", "firstname": "Tawakkol", "surname": "Karman", "motivation": "\"for their non-violent struggle for the safety of women and for women's rights to full participation in peace-building work\"", - "share": "3" + "share": "3", + "birth": { + "year": 2014, + "country": { + "city": "Los Angeles", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2017, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 76 @@ -1614,21 +5392,80 @@ "firstname": "Saul", "surname": "Perlmutter", "motivation": "\"for the discovery of the accelerating expansion of the Universe through observations of distant supernovae\"", - "share": "2" + "share": "2", + "birth": { + "year": 2003, + "country": { + "city": "New York", + "state": "Berlin" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2015, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2010, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] }, { "id": "865", "firstname": "Brian P.", "surname": "Schmidt", "motivation": "\"for the discovery of the accelerating expansion of the Universe through observations of distant supernovae\"", - "share": "4" + "share": "4", + "birth": { + "year": 2020, + "country": { + "city": "Sydney", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2017, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "866", "firstname": "Adam G.", "surname": "Riess", "motivation": "\"for the discovery of the accelerating expansion of the Universe through observations of distant supernovae\"", - "share": "4" + "share": "4", + "birth": { + "year": 1966, + "country": { + "city": "Mumbai", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2013, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 77 @@ -1642,21 +5479,104 @@ "firstname": "Bruce A.", "surname": "Beutler", "motivation": "\"for their discoveries concerning the activation of innate immunity\"", - "share": "4" + "share": "4", + "birth": { + "year": 1964, + "country": { + "city": "Sydney", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2023, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2020, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] }, { "id": "862", "firstname": "Jules A.", "surname": "Hoffmann", "motivation": "\"for their discoveries concerning the activation of innate immunity\"", - "share": "4" + "share": "4", + "birth": { + "year": 1975, + "country": { + "city": "Los Angeles", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2006, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2001, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2001, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "863", "firstname": "Ralph M.", "surname": "Steinman", "motivation": "\"for his discovery of the dendritic cell and its role in adaptive immunity\"", - "share": "2" + "share": "2", + "birth": { + "year": 1998, + "country": { + "city": "New York", + "state": "Maharashtra" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2006, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2015, + "details": { + "category": "chemistry", + "organization": "Fields Medal Committee" + } + } + ] } ], "prize_id": 78 @@ -1670,21 +5590,88 @@ "firstname": "Richard F.", "surname": "Heck", "motivation": "\"for palladium-catalyzed cross couplings in organic synthesis\"", - "share": "3" + "share": "3", + "birth": { + "year": 2013, + "country": { + "city": "Tokyo", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2004, + "details": { + "category": "computer science", + "organization": "Nobel Committee" + } + } + ] }, { "id": "852", "firstname": "Ei-ichi", "surname": "Negishi", "motivation": "\"for palladium-catalyzed cross couplings in organic synthesis\"", - "share": "3" + "share": "3", + "birth": { + "year": 1957, + "country": { + "city": "Tokyo", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2003, + "details": { + "category": "chemistry", + "organization": "Fields Medal Committee" + } + } + ] }, { "id": "853", "firstname": "Akira", "surname": "Suzuki", "motivation": "\"for palladium-catalyzed cross couplings in organic synthesis\"", - "share": "3" + "share": "3", + "birth": { + "year": 2001, + "country": { + "city": "Sydney", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2020, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2001, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2021, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 79 @@ -1698,21 +5685,112 @@ "firstname": "Peter A.", "surname": "Diamond", "motivation": "\"for their analysis of markets with search frictions\"", - "share": "3" + "share": "3", + "birth": { + "year": 1958, + "country": { + "city": "Sydney", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2002, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2008, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "857", "firstname": "Dale T.", "surname": "Mortensen", "motivation": "\"for their analysis of markets with search frictions\"", - "share": "3" + "share": "3", + "birth": { + "year": 2014, + "country": { + "city": "Shanghai", + "state": "Maharashtra" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2008, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2009, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2019, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "858", "firstname": "Christopher A.", "surname": "Pissarides", "motivation": "\"for their analysis of markets with search frictions\"", - "share": "3" + "share": "3", + "birth": { + "year": 1964, + "country": { + "city": "Shanghai", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2008, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2017, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2021, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + } + ] } ], "prize_id": 80 @@ -1726,7 +5804,32 @@ "firstname": "Mario", "surname": "Vargas Llosa", "motivation": "\"for his cartography of structures of power and his trenchant images of the individual's resistance, revolt, and defeat\"", - "share": "1" + "share": "1", + "birth": { + "year": 1979, + "country": { + "city": "Los Angeles", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2020, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2005, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 81 @@ -1740,7 +5843,32 @@ "firstname": "Xiaobo", "surname": "Liu", "motivation": "\"for his long and non-violent struggle for fundamental human rights in China\"", - "share": "1" + "share": "1", + "birth": { + "year": 2011, + "country": { + "city": "London", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2005, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2007, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 82 @@ -1754,14 +5882,72 @@ "firstname": "Andre", "surname": "Geim", "motivation": "\"for groundbreaking experiments regarding the two-dimensional material graphene\"", - "share": "2" + "share": "2", + "birth": { + "year": 1968, + "country": { + "city": "Mumbai", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2020, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2020, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "850", "firstname": "Konstantin", "surname": "Novoselov", "motivation": "\"for groundbreaking experiments regarding the two-dimensional material graphene\"", - "share": "2" + "share": "2", + "birth": { + "year": 1980, + "country": { + "city": "London", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2019, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Fields Medal", + "year": 2019, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Turing Award", + "year": 2013, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + } + ] } ], "prize_id": 83 @@ -1775,7 +5961,32 @@ "firstname": "Robert G.", "surname": "Edwards", "motivation": "\"for the development of in vitro fertilization\"", - "share": "1" + "share": "1", + "birth": { + "year": 1980, + "country": { + "city": "Berlin", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2005, + "details": { + "category": "physics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Fields Medal", + "year": 2007, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 84 @@ -1789,21 +6000,112 @@ "firstname": "Venkatraman", "surname": "Ramakrishnan", "motivation": "\"for studies of the structure and function of the ribosome\"", - "share": "3" + "share": "3", + "birth": { + "year": 1964, + "country": { + "city": "London", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2023, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2006, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "842", "firstname": "Thomas A.", "surname": "Steitz", "motivation": "\"for studies of the structure and function of the ribosome\"", - "share": "3" + "share": "3", + "birth": { + "year": 2022, + "country": { + "city": "Paris", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2010, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2003, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2011, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "843", "firstname": "Ada E.", "surname": "Yonath", "motivation": "\"for studies of the structure and function of the ribosome\"", - "share": "3" + "share": "3", + "birth": { + "year": 1990, + "country": { + "city": "Tokyo", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2001, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2018, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2015, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 85 @@ -1817,14 +6119,48 @@ "firstname": "Elinor", "surname": "Ostrom", "motivation": "\"for her analysis of economic governance, especially the commons\"", - "share": "2" + "share": "2", + "birth": { + "year": 2017, + "country": { + "city": "Paris", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2015, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "847", "firstname": "Oliver E.", "surname": "Williamson", "motivation": "\"for his analysis of economic governance, especially the boundaries of the firm\"", - "share": "2" + "share": "2", + "birth": { + "year": 1991, + "country": { + "city": "London", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2020, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + } + ] } ], "prize_id": 86 @@ -1836,9 +6172,42 @@ { "id": "844", "firstname": "Herta", - "surname": "Müller", + "surname": "M\u00fcller", "motivation": "\"who, with the concentration of poetry and the frankness of prose, depicts the landscape of the dispossessed\"", - "share": "1" + "share": "1", + "birth": { + "year": 2020, + "country": { + "city": "Tokyo", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2020, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2004, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2022, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 87 @@ -1852,7 +6221,40 @@ "firstname": "Barack", "surname": "Obama", "motivation": "\"for his extraordinary efforts to strengthen international diplomacy and cooperation between peoples\"", - "share": "1" + "share": "1", + "birth": { + "year": 1974, + "country": { + "city": "Sao Paulo", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2016, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2012, + "details": { + "category": "chemistry", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2016, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 88 @@ -1866,21 +6268,80 @@ "firstname": "Charles K.", "surname": "Kao", "motivation": "\"for groundbreaking achievements concerning the transmission of light in fibers for optical communication\"", - "share": "2" + "share": "2", + "birth": { + "year": 1954, + "country": { + "city": "Shanghai", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2008, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "839", "firstname": "Willard S.", "surname": "Boyle", "motivation": "\"for the invention of an imaging semiconductor circuit - the CCD sensor\"", - "share": "4" + "share": "4", + "birth": { + "year": 1985, + "country": { + "city": "Berlin", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2021, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2012, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "840", "firstname": "George E.", "surname": "Smith", "motivation": "\"for the invention of an imaging semiconductor circuit - the CCD sensor\"", - "share": "4" + "share": "4", + "birth": { + "year": 1966, + "country": { + "city": "Shanghai", + "state": "Berlin" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2021, + "details": { + "category": "computer science", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 89 @@ -1894,21 +6355,104 @@ "firstname": "Elizabeth H.", "surname": "Blackburn", "motivation": "\"for the discovery of how chromosomes are protected by telomeres and the enzyme telomerase\"", - "share": "3" + "share": "3", + "birth": { + "year": 1959, + "country": { + "city": "Mumbai", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2016, + "details": { + "category": "computer science", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2004, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] }, { "id": "836", "firstname": "Carol W.", "surname": "Greider", "motivation": "\"for the discovery of how chromosomes are protected by telomeres and the enzyme telomerase\"", - "share": "3" + "share": "3", + "birth": { + "year": 1986, + "country": { + "city": "Paris", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2002, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2019, + "details": { + "category": "physics", + "organization": "Fields Medal Committee" + } + } + ] }, { "id": "837", "firstname": "Jack W.", "surname": "Szostak", "motivation": "\"for the discovery of how chromosomes are protected by telomeres and the enzyme telomerase\"", - "share": "3" + "share": "3", + "birth": { + "year": 1951, + "country": { + "city": "New York", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2015, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2023, + "details": { + "category": "chemistry", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2014, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + } + ] } ], "prize_id": 90 @@ -1922,21 +6466,88 @@ "firstname": "Osamu", "surname": "Shimomura", "motivation": "\"for the discovery and development of the green fluorescent protein, GFP\"", - "share": "3" + "share": "3", + "birth": { + "year": 1974, + "country": { + "city": "Mumbai", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2010, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + } + ] }, { "id": "830", "firstname": "Martin", "surname": "Chalfie", "motivation": "\"for the discovery and development of the green fluorescent protein, GFP\"", - "share": "3" + "share": "3", + "birth": { + "year": 1960, + "country": { + "city": "Shanghai", + "state": "England" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2009, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2023, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + } + ] }, { "id": "831", "firstname": "Roger Y.", "surname": "Tsien", "motivation": "\"for the discovery and development of the green fluorescent protein, GFP\"", - "share": "3" + "share": "3", + "birth": { + "year": 2010, + "country": { + "city": "Sydney", + "state": "Maharashtra" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2004, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2011, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + } + ] } ], "prize_id": 91 @@ -1950,7 +6561,32 @@ "firstname": "Paul", "surname": "Krugman", "motivation": "\"for his analysis of trade patterns and location of economic activity\"", - "share": "1" + "share": "1", + "birth": { + "year": 1982, + "country": { + "city": "Mumbai", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2019, + "details": { + "category": "physics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2013, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + } + ] } ], "prize_id": 92 @@ -1962,9 +6598,42 @@ { "id": "832", "firstname": "Jean-Marie Gustave", - "surname": "Le Clézio", + "surname": "Le Cl\u00e9zio", "motivation": "\"author of new departures, poetic adventure and sensual ecstasy, explorer of a humanity beyond and below the reigning civilization\"", - "share": "1" + "share": "1", + "birth": { + "year": 1951, + "country": { + "city": "London", + "state": "Tokyo" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2006, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2014, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2009, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + } + ] } ], "prize_id": 93 @@ -1978,7 +6647,40 @@ "firstname": "Martti", "surname": "Ahtisaari", "motivation": "\"for his important efforts, on several continents and over more than three decades, to resolve international conflicts\"", - "share": "1" + "share": "1", + "birth": { + "year": 1996, + "country": { + "city": "Mumbai", + "state": "Shanghai" + } + }, + "awards": [ + { + "award_name": "Fields Medal", + "year": 2008, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2002, + "details": { + "category": "chemistry", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2010, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + } + ] } ], "prize_id": 94 @@ -1992,21 +6694,112 @@ "firstname": "Yoichiro", "surname": "Nambu", "motivation": "\"for the discovery of the mechanism of spontaneous broken symmetry in subatomic physics\"", - "share": "2" + "share": "2", + "birth": { + "year": 2013, + "country": { + "city": "London", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2000, + "details": { + "category": "chemistry", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Turing Award", + "year": 2001, + "details": { + "category": "chemistry", + "organization": "Fields Medal Committee" + } + } + ] }, { "id": "827", "firstname": "Makoto", "surname": "Kobayashi", "motivation": "\"for the discovery of the origin of the broken symmetry which predicts the existence of at least three families of quarks in nature\"", - "share": "4" + "share": "4", + "birth": { + "year": 1978, + "country": { + "city": "Sydney", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2017, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Fields Medal", + "year": 2006, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2020, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + } + ] }, { "id": "828", "firstname": "Toshihide", "surname": "Maskawa", "motivation": "\"for the discovery of the origin of the broken symmetry which predicts the existence of at least three families of quarks in nature\"", - "share": "4" + "share": "4", + "birth": { + "year": 2005, + "country": { + "city": "Berlin", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2012, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2023, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2009, + "details": { + "category": "mathematics", + "organization": "Fields Medal Committee" + } + } + ] } ], "prize_id": 95 @@ -2020,21 +6813,80 @@ "firstname": "Harald", "surname": "zur Hausen", "motivation": "\"for his discovery of human papilloma viruses causing cervical cancer\"", - "share": "2" + "share": "2", + "birth": { + "year": 1960, + "country": { + "city": "Sydney", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2017, + "details": { + "category": "mathematics", + "organization": "Turing Award Committee" + } + } + ] }, { "id": "824", - "firstname": "Françoise", - "surname": "Barré-Sinoussi", + "firstname": "Fran\u00e7oise", + "surname": "Barr\u00e9-Sinoussi", "motivation": "\"for their discovery of human immunodeficiency virus\"", - "share": "4" + "share": "4", + "birth": { + "year": 1983, + "country": { + "city": "Mumbai", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2021, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "825", "firstname": "Luc", "surname": "Montagnier", "motivation": "\"for their discovery of human immunodeficiency virus\"", - "share": "4" + "share": "4", + "birth": { + "year": 1952, + "country": { + "city": "Shanghai", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2006, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Lasker Award", + "year": 2002, + "details": { + "category": "chemistry", + "organization": "Wolf Foundation" + } + } + ] } ], "prize_id": 96 @@ -2048,7 +6900,32 @@ "firstname": "Gerhard", "surname": "Ertl", "motivation": "\"for his studies of chemical processes on solid surfaces\"", - "share": "1" + "share": "1", + "birth": { + "year": 1998, + "country": { + "city": "Sydney", + "state": "Sao Paulo" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2014, + "details": { + "category": "chemistry", + "organization": "Lasker Foundation" + } + }, + { + "award_name": "Turing Award", + "year": 2017, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 97 @@ -2062,21 +6939,96 @@ "firstname": "Leonid", "surname": "Hurwicz", "motivation": "\"for having laid the foundations of mechanism design theory\"", - "share": "3" + "share": "3", + "birth": { + "year": 1963, + "country": { + "city": "Los Angeles", + "state": "Texas" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2008, + "details": { + "category": "mathematics", + "organization": "Wolf Foundation" + } + }, + { + "award_name": "Wolf Prize in Physics", + "year": 2022, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + } + ] }, { "id": "821", "firstname": "Eric S.", "surname": "Maskin", "motivation": "\"for having laid the foundations of mechanism design theory\"", - "share": "3" + "share": "3", + "birth": { + "year": 1960, + "country": { + "city": "Tokyo", + "state": "Berlin" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2010, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Lasker Award", + "year": 2010, + "details": { + "category": "computer science", + "organization": "Fields Medal Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2018, + "details": { + "category": "mathematics", + "organization": "Lasker Foundation" + } + } + ] }, { "id": "822", "firstname": "Roger B.", "surname": "Myerson", "motivation": "\"for having laid the foundations of mechanism design theory\"", - "share": "3" + "share": "3", + "birth": { + "year": 1978, + "country": { + "city": "Paris", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Wolf Prize in Physics", + "year": 2001, + "details": { + "category": "physics", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 98 @@ -2090,7 +7042,24 @@ "firstname": "Doris", "surname": "Lessing", "motivation": "\"that epicist of the female experience, who with scepticism, fire and visionary power has subjected a divided civilisation to scrutiny\"", - "share": "1" + "share": "1", + "birth": { + "year": 1965, + "country": { + "city": "Los Angeles", + "state": "California" + } + }, + "awards": [ + { + "award_name": "Lasker Award", + "year": 2010, + "details": { + "category": "computer science", + "organization": "Lasker Foundation" + } + } + ] } ], "prize_id": 99 @@ -2103,14 +7072,64 @@ "id": "818", "motivation": "\"for their efforts to build up and disseminate greater knowledge about man-made climate change, and to lay the foundations for the measures that are needed to counteract such change\"", "share": "2", - "firstname": "Intergovernmental Panel on Climate Change" + "firstname": "Intergovernmental Panel on Climate Change", + "birth": { + "year": 2019, + "country": { + "city": "New York", + "state": "New South Wales" + } + }, + "awards": [ + { + "award_name": "Turing Award", + "year": 2011, + "details": { + "category": "physics", + "organization": "Turing Award Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2021, + "details": { + "category": "chemistry", + "organization": "Nobel Committee" + } + }, + { + "award_name": "Nobel Prize in Chemistry", + "year": 2016, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] }, { "id": "819", "firstname": "Al", "surname": "Gore", "motivation": "\"for their efforts to build up and disseminate greater knowledge about man-made climate change, and to lay the foundations for the measures that are needed to counteract such change\"", - "share": "2" + "share": "2", + "birth": { + "year": 1997, + "country": { + "city": "Sydney", + "state": "Ile-de-France" + } + }, + "awards": [ + { + "award_name": "Nobel Prize in Chemistry", + "year": 2012, + "details": { + "category": "mathematics", + "organization": "Nobel Committee" + } + } + ] } ], "prize_id": 100 diff --git a/script/test-setup.js b/script/test-setup.js new file mode 100644 index 0000000..433f111 --- /dev/null +++ b/script/test-setup.js @@ -0,0 +1,236 @@ +import { exec, execSync } from 'child_process'; +import { CosmosClient } from '@azure/cosmos'; +import net from 'net'; +import path from 'path'; +import fs from 'fs'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +// Azure Cosmos DB configuration +const cosmosConfig = { + endpoint: process.env.AZURE_COSMOS_ENDPOINT, + key: process.env.AZURE_COSMOS_KEY, + databaseId: process.env.AZURE_COSMOS_DB_NAME, + containerId: 'TestNobelLaureates' // Use the existing container +}; + +// Validate Cosmos DB configuration +Object.entries(cosmosConfig).forEach(([key, value]) => { + if (typeof value !== 'string' || value.trim() === '') { + throw new Error(`Invalid or missing Cosmos DB configuration: ${key}`); + } +}); + +const client = new CosmosClient({ endpoint: cosmosConfig.endpoint, key: cosmosConfig.key }); + +function readTestData() { + const testDataPath = path.join(__dirname, 'data', 'data.json'); + try { + const rawData = fs.readFileSync(testDataPath, 'utf8'); + return JSON.parse(rawData); + } catch (error) { + console.error('Error reading test data:', error); + throw error; + } +} + +async function setupCosmosEmulatorDB() { + // Disable certificate validation for local emulator + process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0 + + console.log('Setting up Azure Cosmos DB...'); + console.log(`Database ID: ${cosmosConfig.databaseId}`); + console.log(`Container ID: ${cosmosConfig.containerId}`); + + try { + const { database } = await client.databases.createIfNotExists({ id: cosmosConfig.databaseId }); + const { container } = await database.containers.createIfNotExists( + { + id: cosmosConfig.containerId, + partitionKey: { paths: ['/year'] }, + indexingPolicy: { + "indexingMode": "consistent", + "automatic": true, + "includedPaths": [ + { + "path": "/*" + } + ], + "excludedPaths": [ + { + "path": "/\"_etag\"/?" + } + ], + "compositeIndexes": [ + [ + { + "path": "/overallMotivation", + "order": "descending" + }, + { + "path": "/prize_id", + "order": "descending" + } + ], + [ + { + "path": "/overallMotivation", + "order": "ascending" + }, + { + "path": "/prize_id", + "order": "descending" + } + ], + [ + { + "path": "/year", + "order": "ascending" + }, + { + "path": "/prize_id", + "order": "ascending" + } + ], + [ + { + "path": "/year", + "order": "ascending" + }, + { + "path": "/prize_id", + "order": "descending" + } + ] + ] + } + }); + + console.log('Deleting existing data...'); + const { resources: items } = await container.items.readAll().fetchAll(); + if (items.length > 0) { + for (const item of items) { + await container.item(item.id, item.year).delete(); + } + console.log(`${items.length} items deleted.`); + } + + console.log('Inserting new test data...'); + const newItems = readTestData(); + for (const item of newItems) { + await container.items.create(item); + } + console.log(`${newItems.length} items inserted.`); + console.log('Data setup completed.'); + } catch (error) { + console.error('Error setting up Cosmos DB:', error); + if (error.code) { + console.error(`Error code: ${error.code}`); + } + if (error.body) { + console.error('Error details:', error.body); + } + throw error; + } +} + +function findVacantPort(startPort = 8000) { + return new Promise((resolve, reject) => { + const server = net.createServer(); + server.listen(startPort, () => { + const port = server.address().port; + server.close(() => resolve(port)); + }); + server.on('error', (err) => { + if (err.code === 'EADDRINUSE') { + findVacantPort(startPort + 1).then(resolve, reject); + } else { + reject(err); + } + }); + }); +} + +async function runTests(setupEmulatorData) { + const projectRoot = path.resolve(__dirname, '..'); + const logFile = path.join(projectRoot, 'server-output.log'); + let serverProcess = null; + + try { + if (setupEmulatorData) { + await setupCosmosEmulatorDB(); + } else { + console.log('Skipping Cosmos DB setup as --setup-emulator-data flag is not set.'); + } + + console.log('Running CLI update...'); + execSync('npm run cli update', { stdio: 'inherit', cwd: projectRoot }); + console.log('CLI update completed.'); + + const port = await findVacantPort(); + console.log(`Found vacant port: ${port}`); + + const startCommand = `npm run start serve -- --configuration . --port ${port} | jq -R -r '. as $line | try fromjson catch $line'`; + const testCommand = `ndc-test replay --endpoint http://0.0.0.0:${port} --snapshots-dir ${path.join(projectRoot, 'ndc-test-snapshots')}`; + + console.log('Starting server...'); + serverProcess = exec(startCommand, { cwd: projectRoot }); + + // Save server output to file + const logStream = fs.createWriteStream(logFile); + serverProcess.stdout.pipe(logStream); + serverProcess.stderr.pipe(logStream); + + // Wait for server to start (adjust timeout as needed) + await new Promise(resolve => setTimeout(resolve, 5000)); + + console.log('Running tests...'); + execSync(testCommand, { stdio: 'inherit', cwd: projectRoot }); + + console.log('Tests completed successfully.'); + } catch (error) { + console.error('An error occurred:', error); + + // Output contents of log file + console.error('Server output:'); + try { + const logContents = fs.readFileSync(logFile, 'utf8'); + console.error(logContents); + } catch (readError) { + console.error('Failed to read server output log:', readError); + } + throw error; // Re-throw the error to be caught in the main function + } finally { + // Terminate the server process + if (serverProcess) { + console.log('Terminating server process...'); + serverProcess.kill('SIGTERM'); + } + + // Clean up log file + try { + fs.unlinkSync(logFile); + } catch (unlinkError) { + console.error('Failed to remove log file:', unlinkError); + } + + console.log('Test setup script completed.'); + } +} + +async function main() { + try { + const args = process.argv.slice(2); + const setupData = args.includes('--setup-emulator-data'); + + await runTests(setupData); + process.exit(0); // Successful execution + } catch (error) { + console.error('An error occurred in the main function:', error); + process.exit(1); // Exit with error status + } +} + +main(); diff --git a/src/cli/config.ts b/src/cli/config.ts index 776ec5a..b2a2f6f 100644 --- a/src/cli/config.ts +++ b/src/cli/config.ts @@ -1,42 +1,56 @@ import { Database } from "@azure/cosmos"; -import { CollectionDefinition, CollectionDefinitions, CollectionsSchema, NamedObjectTypeDefinition, ScalarTypeDefinitions, getJSONScalarTypes } from "../schema" -import { BuiltInScalarTypeName, ObjectTypeDefinitions, TypeDefinition, ObjectTypePropertiesMap } from "../schema"; - -import { Container } from "@azure/cosmos" - -import { InputData, jsonInputForTargetLanguage, quicktype } from "quicktype-core"; -import { runSQLQuery, constructCosmosDbClient } from "../cosmosDb" +import { + CollectionDefinition, + CollectionDefinitions, + CollectionsSchema, + NamedObjectTypeDefinition, + ScalarTypeDefinitions, + getJSONScalarTypes, +} from "../connector/schema"; +import { + BuiltInScalarTypeName, + ObjectTypeDefinitions, + TypeDefinition, + ObjectTypePropertiesMap, +} from "../connector/schema"; + +import { Container } from "@azure/cosmos"; + +import { + InputData, + jsonInputForTargetLanguage, + quicktype, +} from "quicktype-core"; +import { runSQLQuery, constructCosmosDbClient } from "../connector/db/cosmosDb"; import { exit } from "process"; import fs from "fs"; import { promisify } from "util"; import { $RefParser } from "@apidevtools/json-schema-ref-parser"; - export type RawConfiguration = { - azure_cosmos_key: string, - azure_cosmos_db_endpoint: string, - azure_cosmos_db_name: string, - azure_cosmos_no_of_rows_to_fetch: number | null -} + azure_cosmos_key: string; + azure_cosmos_db_endpoint: string; + azure_cosmos_db_name: string; + azure_cosmos_no_of_rows_to_fetch: number | null; +}; type JSONSchemaProperty = { - type: string, - $ref: string, - items?: JSONSchemaProperty -} + type: string; + $ref: string; + items?: JSONSchemaProperty; +}; type JSONSchemaDefinition = { - type: string, - additionalProperties: boolean, - properties?: Record, - title: string, -} + type: string; + additionalProperties: boolean; + properties?: Record; + title: string; +}; export type JSONSchema = { - definitions: Record, - $ref: string, -} - + definitions: Record; + $ref: string; +}; /** * Fetches at-most `n` latest updated rows from the given container @@ -46,144 +60,162 @@ export type JSONSchema = { * @returns The latest at-most `n` rows from the `container`. **/ -export async function fetchLatestNRowsFromContainer(n: number, container: Container): Promise { - const querySpec = { - query: `SELECT * FROM ${container.id} c ORDER BY c._ts DESC OFFSET 0 LIMIT ${n}`, - parameters: [] - } - - return await runSQLQuery(querySpec, container) +export async function fetchLatestNRowsFromContainer( + n: number, + container: Container, +): Promise { + const querySpec = { + query: `SELECT * FROM ${container.id} c ORDER BY c._ts DESC OFFSET 0 LIMIT ${n}`, + parameters: [], + }; + + return await runSQLQuery(querySpec, container); } +export async function inferJSONSchemaFromContainerRows( + rows: string[], + containerTypeName: string, +): Promise { + const jsonInput = jsonInputForTargetLanguage("schema"); -export async function inferJSONSchemaFromContainerRows(rows: string[], containerTypeName: string): Promise { - const jsonInput = jsonInputForTargetLanguage("schema"); - - await jsonInput.addSource({ - name: containerTypeName, - samples: rows.map(x => JSON.stringify(x)) - }); - - const inputData = new InputData(); - inputData.addInput(jsonInput); + await jsonInput.addSource({ + name: containerTypeName, + samples: rows.map((x) => JSON.stringify(x)), + }); - let jsonSchema = await quicktype({ - inputData, - lang: "schema" - }); + const inputData = new InputData(); + inputData.addInput(jsonInput); - let rawJSONSchemaOutput: any = jsonSchema.lines.join("\n"); + let jsonSchema = await quicktype({ + inputData, + lang: "schema", + }); - return JSON.parse(rawJSONSchemaOutput) + let rawJSONSchemaOutput: any = jsonSchema.lines.join("\n"); + return JSON.parse(rawJSONSchemaOutput); } -function getPropertyTypeDefn(property: JSONSchemaProperty, $refs: $RefParser): TypeDefinition | null { - if (property.$ref !== undefined && property.$ref !== null) { - - const referencedPropertyDefn = $refs.$refs.get(property.$ref) as JSONSchemaDefinition; - - if (referencedPropertyDefn.type === "object") { - return { - type: "named", - name: referencedPropertyDefn.title, - kind: "object" - } - } else if (referencedPropertyDefn.type === "string") { - return { - type: "named", - name: BuiltInScalarTypeName.String, - kind: "scalar" - } - } else { - console.log("Warning: Could not infer the type for referenced property", property); - - } - - - } else if (property.type == "null") { - // We don't have enough information to predict anything about the property. So, just - // return null. - return null - } else if (property.type == "array") { - if (property.items !== undefined) { - const elementType = getPropertyTypeDefn(property.items, $refs); - - if (elementType !== null) { - return { - "type": "array", - "elementType": elementType - } - } - - } - return null - } else if (property.type == "string") { - return { - "type": "named", - name: BuiltInScalarTypeName.String, - kind: "scalar" - } - } else if (property.type == "number") { - return { - "type": "named", - name: BuiltInScalarTypeName.Number, - kind: "scalar" - } +function getPropertyTypeDefn( + property: JSONSchemaProperty, + $refs: $RefParser, +): TypeDefinition | null { + if (property.$ref !== undefined && property.$ref !== null) { + const referencedPropertyDefn = $refs.$refs.get( + property.$ref, + ) as JSONSchemaDefinition; + + if (referencedPropertyDefn.type === "object") { + return { + type: "named", + name: referencedPropertyDefn.title, + kind: "object", + }; + } else if (referencedPropertyDefn.type === "string") { + return { + type: "named", + name: BuiltInScalarTypeName.String, + kind: "scalar", + }; + } else { + console.log( + "Warning: Could not infer the type for referenced property", + property, + ); } - else if (property.type == "integer") { - return { - "type": "named", - name: BuiltInScalarTypeName.Number, - kind: "scalar" - } - } else if (property.type == "boolean") { + } else if (property.type == "null") { + // We don't have enough information to predict anything about the property. So, just + // return null. + return null; + } else if (property.type == "array") { + if (property.items !== undefined) { + const elementType = getPropertyTypeDefn(property.items, $refs); + + if (elementType !== null) { return { - "type": "named", - name: BuiltInScalarTypeName.Boolean, - kind: "scalar" - } + type: "array", + elementType: elementType, + }; + } } + return null; + } else if (property.type == "string") { + return { + type: "named", + name: BuiltInScalarTypeName.String, + kind: "scalar", + }; + } else if (property.type == "number") { + return { + type: "named", + name: BuiltInScalarTypeName.Number, + kind: "scalar", + }; + } else if (property.type == "integer") { + return { + type: "named", + name: BuiltInScalarTypeName.Number, + kind: "scalar", + }; + } else if (property.type == "boolean") { + return { + type: "named", + name: BuiltInScalarTypeName.Boolean, + kind: "scalar", + }; + } - return null + return null; } -export async function getObjectTypeDefinitionsFromJSONSchema(containerJSONSchema: JSONSchema): Promise { - var objectTypeDefinitions: ObjectTypeDefinitions = {}; - let parser = new $RefParser(); - - const $refs = await parser.resolve(JSON.parse(JSON.stringify(containerJSONSchema))); - Object.entries(containerJSONSchema.definitions).forEach(([objectTypeName, objectTypeDefinition]) => { - if (objectTypeDefinition.type == "object") { - var objectTypeProperties: ObjectTypePropertiesMap = {}; - - if (objectTypeDefinition.properties !== undefined) { - - Object.entries(objectTypeDefinition.properties).map(([propertyName, propertyDefn]) => { - - let propertyTypeDefn = getPropertyTypeDefn(propertyDefn, parser); - - let legacyProperty = ['_rid', '_self', '_etag', '_attachments', '_ts'] - if (propertyTypeDefn !== null && !legacyProperty.includes(propertyName)) { - objectTypeProperties[propertyName] = { - propertyName: propertyName, - description: null, - type: propertyTypeDefn - }; - } - - }) - - objectTypeDefinitions[objectTypeName] = { - description: null, - properties: objectTypeProperties - } - } +export async function getObjectTypeDefinitionsFromJSONSchema( + containerJSONSchema: JSONSchema, +): Promise { + var objectTypeDefinitions: ObjectTypeDefinitions = {}; + let parser = new $RefParser(); + + const $refs = await parser.resolve( + JSON.parse(JSON.stringify(containerJSONSchema)), + ); + Object.entries(containerJSONSchema.definitions).forEach( + ([objectTypeName, objectTypeDefinition]) => { + if (objectTypeDefinition.type == "object") { + var objectTypeProperties: ObjectTypePropertiesMap = {}; + + if (objectTypeDefinition.properties !== undefined) { + Object.entries(objectTypeDefinition.properties).map( + ([propertyName, propertyDefn]) => { + let propertyTypeDefn = getPropertyTypeDefn(propertyDefn, parser); + + let legacyProperty = [ + "_rid", + "_self", + "_etag", + "_attachments", + "_ts", + ]; + if ( + propertyTypeDefn !== null && + !legacyProperty.includes(propertyName) + ) { + objectTypeProperties[propertyName] = { + propertyName: propertyName, + description: null, + type: propertyTypeDefn, + }; + } + }, + ); + objectTypeDefinitions[objectTypeName] = { + description: null, + properties: objectTypeProperties, + }; } - } - ) - return objectTypeDefinitions + } + }, + ); + return objectTypeDefinitions; } /** @@ -195,79 +227,94 @@ export async function getObjectTypeDefinitionsFromJSONSchema(containerJSONSchema * @param {number} nRows - Number of rows to be read per container to infer the schema of the container. * @returns {Promise { - - let collectionDefinitions: CollectionDefinitions = {}; - - let objectTypeDefinitions: ObjectTypeDefinitions = {}; - - const scalarTypeDefinitions: ScalarTypeDefinitions = getJSONScalarTypes(); - - const { resources: allContainers } = await database.containers.readAll().fetchAll(); - - - for (const container of allContainers) { - const dbContainer = database.container(container.id); - - const nContainerRows = await fetchLatestNRowsFromContainer(nRows, dbContainer); - nContainerRows.reverse(); - const containerJsonSchema = await inferJSONSchemaFromContainerRows(nContainerRows, container.id); - - const containerObjectTypeDefinitions = await getObjectTypeDefinitionsFromJSONSchema(containerJsonSchema); - - const collectionObjectType: NamedObjectTypeDefinition = { - type: "named", - name: containerJsonSchema.$ref.split('/').pop() as string, - kind: "object" - }; - - const collectionDefinition: CollectionDefinition = { - description: null, - arguments: [], - resultType: collectionObjectType - }; +async function getCollectionsSchema( + database: Database, + nRows: number, +): Promise { + let collectionDefinitions: CollectionDefinitions = {}; + + let objectTypeDefinitions: ObjectTypeDefinitions = {}; + + const scalarTypeDefinitions: ScalarTypeDefinitions = getJSONScalarTypes(); + + const { resources: allContainers } = await database.containers + .readAll() + .fetchAll(); + + for (const container of allContainers) { + const dbContainer = database.container(container.id); + + const nContainerRows = await fetchLatestNRowsFromContainer( + nRows, + dbContainer, + ); + nContainerRows.reverse(); + const containerJsonSchema = await inferJSONSchemaFromContainerRows( + nContainerRows, + container.id, + ); + + const containerObjectTypeDefinitions = + await getObjectTypeDefinitionsFromJSONSchema(containerJsonSchema); + + const collectionObjectType: NamedObjectTypeDefinition = { + type: "named", + name: containerJsonSchema.$ref.split("/").pop() as string, + kind: "object", + }; - objectTypeDefinitions = { ...objectTypeDefinitions, ...containerObjectTypeDefinitions }; - collectionDefinitions[container.id] = collectionDefinition; - } + const collectionDefinition: CollectionDefinition = { + description: null, + arguments: [], + resultType: collectionObjectType, + }; - let schema = { - collections: collectionDefinitions, - objectTypes: objectTypeDefinitions, - scalarTypes: scalarTypeDefinitions, + objectTypeDefinitions = { + ...objectTypeDefinitions, + ...containerObjectTypeDefinitions, }; + collectionDefinitions[container.id] = collectionDefinition; + } - return schema + let schema = { + collections: collectionDefinitions, + objectTypes: objectTypeDefinitions, + scalarTypes: scalarTypeDefinitions, + }; + return schema; } export async function generateConnectorConfig(outputConfigDir: string) { - const rowsToFetch = process.env["AZURE_COSMOS_NO_OF_ROWS_TO_FETCH"] ?? "100"; - - try { - const client = constructCosmosDbClient(); - const schema = await getCollectionsSchema(client.dbClient, parseInt(rowsToFetch)); - const cosmosKey = client.connectionDetails.key; - const cosmosEndpoint = client.connectionDetails.endpoint; - const cosmosDbName = client.connectionDetails.databaseName; - - const response: any = { - connection: { - endpoint: cosmosEndpoint, - key: cosmosKey, - databaseName: cosmosDbName - }, - schema - }; - - const writeFile = promisify(fs.writeFile); - - await writeFile(`${outputConfigDir}/config.json`, JSON.stringify(response, null, 2)); - + const rowsToFetch = process.env["AZURE_COSMOS_NO_OF_ROWS_TO_FETCH"] ?? "100"; + + try { + const client = constructCosmosDbClient(); + const schema = await getCollectionsSchema( + client.dbClient, + parseInt(rowsToFetch), + ); + const cosmosKey = client.connectionDetails.key; + const cosmosEndpoint = client.connectionDetails.endpoint; + const cosmosDbName = client.connectionDetails.databaseName; + + const response: any = { + connection: { + endpoint: cosmosEndpoint, + key: cosmosKey, + databaseName: cosmosDbName, + }, + schema, + }; - } catch (error) { - console.log("Error while generating the config", error); - exit(1) - } + const writeFile = promisify(fs.writeFile); + await writeFile( + `${outputConfigDir}/config.json`, + JSON.stringify(response, null, 2), + ); + } catch (error) { + console.log("Error while generating the config", error); + exit(1); + } } diff --git a/src/cli/index.ts b/src/cli/index.ts index 915c8e0..2b5e3eb 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -2,7 +2,7 @@ import { Command, Option } from "commander"; import * as updateCmd from "./update"; -import { createConnector } from "../connector"; +import { createConnector } from "../connector/connector"; import { version } from "../../package.json" import * as sdk from "@hasura/ndc-sdk-typescript"; diff --git a/src/connector.ts b/src/connector.ts deleted file mode 100644 index 31744b2..0000000 --- a/src/connector.ts +++ /dev/null @@ -1,105 +0,0 @@ -import * as sdk from "@hasura/ndc-sdk-typescript"; -import { CollectionsSchema, getNdcSchemaResponse } from "./schema" -import { constructCosmosDbClient } from "./cosmosDb"; -import { Database } from "@azure/cosmos"; -import { executeQuery } from "./execution"; -import { readFileSync } from "fs"; - - -export type Configuration = ConnectorConfig; - -export type ConnectorConfig = { - connection: { - endpoint: string, - key: string, - databaseName: string - } - schema: CollectionsSchema -} - -export type State = { - databaseClient: Database -}; - -export function createConnector(): sdk.Connector { - - const connector: sdk.Connector = { - parseConfiguration: async function(configurationDir: string): Promise { - - try { - const configLocation = `${configurationDir}/config.json`; - const fileContent = readFileSync(configLocation, 'utf8'); - const configObject: ConnectorConfig = JSON.parse(fileContent); - return Promise.resolve(configObject) - - } catch (error) { - console.error("Failed to parse configuration:", error); - throw new sdk.InternalServerError( - "Internal Server Error, server configuration is invalid", - {} - ); - } - - - }, - - tryInitState: async function(_: Configuration, __: unknown): Promise { - try { - const databaseClient = constructCosmosDbClient().dbClient; - return Promise.resolve({ - databaseClient - }) - } catch (error) { - console.error("Failed to initialize the state of the connector", error); - throw new sdk.InternalServerError( - `Internal server error, failed to initialize the state of the connector - ${error}`, {} - ) - } - - }, - - getSchema: async function(configuration: Configuration): Promise { - if (!configuration.schema) { - throw new sdk.Forbidden("Internal server error, server configuration not found") - } - return Promise.resolve(getNdcSchemaResponse(configuration.schema)) - - }, - - getCapabilities(_: Configuration): sdk.Capabilities { - return { - query: { - nested_fields: {}, - }, - mutation: {} - - } - }, - - query: async function(configuration: Configuration, state: State, request: sdk.QueryRequest): Promise { - return executeQuery(request, configuration.schema, state.databaseClient) - }, - - mutation: async function(configuration: Configuration, state: State, request: sdk.MutationRequest): Promise { - throw new Error("Not implemented") - }, - - queryExplain: function(configuration: Configuration, state: State, request: sdk.QueryRequest): Promise { - throw new Error("Function not implemented."); - }, - - mutationExplain: function(configuration: Configuration, state: State, request: sdk.MutationRequest): Promise { - throw new Error("Function not implemented."); - }, - - fetchMetrics: async function(configuration: Configuration, state: State): Promise { - return undefined; - }, - - - } - - - return connector; - -} diff --git a/src/connector/connector.ts b/src/connector/connector.ts new file mode 100644 index 0000000..0642dd1 --- /dev/null +++ b/src/connector/connector.ts @@ -0,0 +1,123 @@ +import * as sdk from "@hasura/ndc-sdk-typescript"; +import { CollectionsSchema, getNdcSchemaResponse } from "./schema"; +import { constructCosmosDbClient } from "./db/cosmosDb"; +import { Database } from "@azure/cosmos"; +import { executeQuery } from "./execution"; +import { readFileSync } from "fs"; + +export type Configuration = ConnectorConfig; + +export type ConnectorConfig = { + connection: { + endpoint: string; + key: string; + databaseName: string; + }; + schema: CollectionsSchema; +}; + +export type State = { + databaseClient: Database; +}; + +export function createConnector(): sdk.Connector { + const connector: sdk.Connector = { + parseConfiguration: async function ( + configurationDir: string, + ): Promise { + try { + const configLocation = `${configurationDir}/config.json`; + const fileContent = readFileSync(configLocation, "utf8"); + const configObject: ConnectorConfig = JSON.parse(fileContent); + return Promise.resolve(configObject); + } catch (error) { + console.error("Failed to parse configuration:", error); + throw new sdk.InternalServerError( + "Internal Server Error, server configuration is invalid", + {}, + ); + } + }, + + tryInitState: async function ( + _: Configuration, + __: unknown, + ): Promise { + try { + const databaseClient = constructCosmosDbClient().dbClient; + return Promise.resolve({ + databaseClient, + }); + } catch (error) { + console.error("Failed to initialize the state of the connector", error); + throw new sdk.InternalServerError( + `Internal server error, failed to initialize the state of the connector - ${error}`, + {}, + ); + } + }, + + getSchema: async function ( + configuration: Configuration, + ): Promise { + if (!configuration.schema) { + throw new sdk.Forbidden( + "Internal server error, server configuration not found", + ); + } + return Promise.resolve(getNdcSchemaResponse(configuration.schema)); + }, + + getCapabilities(_: Configuration): sdk.Capabilities { + return { + query: { + nested_fields: { + filter_by: {}, + }, + }, + mutation: {}, + }; + }, + + query: async function ( + configuration: Configuration, + state: State, + request: sdk.QueryRequest, + ): Promise { + return executeQuery(request, configuration.schema, state.databaseClient); + }, + + mutation: async function ( + configuration: Configuration, + state: State, + request: sdk.MutationRequest, + ): Promise { + throw new Error("Not implemented"); + }, + + queryExplain: function ( + configuration: Configuration, + state: State, + request: sdk.QueryRequest, + ): Promise { + throw new Error("Function not implemented."); + }, + + mutationExplain: function ( + configuration: Configuration, + state: State, + request: sdk.MutationRequest, + ): Promise { + throw new Error("Function not implemented."); + }, + + fetchMetrics: async function ( + configuration: Configuration, + state: State, + ): Promise { + return undefined; + }, + }; + + return connector; +} diff --git a/src/cosmosDb.ts b/src/connector/db/cosmosDb.ts similarity index 100% rename from src/cosmosDb.ts rename to src/connector/db/cosmosDb.ts diff --git a/src/connector/execution.ts b/src/connector/execution.ts new file mode 100644 index 0000000..c94bc74 --- /dev/null +++ b/src/connector/execution.ts @@ -0,0 +1,517 @@ +import * as sdk from "@hasura/ndc-sdk-typescript"; +import * as schema from "./schema"; +import * as sql from "./sql/sqlGeneration"; +import { Database } from "@azure/cosmos"; +import { runSQLQuery } from "./db/cosmosDb"; + +function validateOrderBy( + orderBy: sdk.OrderBy, + collectionObjectType: schema.ObjectTypeDefinition, +) { + for (const orderByElement of orderBy.elements) { + switch (orderByElement.target.type) { + case "column": + if (orderByElement.target.path.length > 0) { + throw new sdk.NotSupported( + "Relationships references are not supported in order by.", + ); + } + if (!(orderByElement.target.name in collectionObjectType.properties)) { + throw new sdk.BadRequest( + `Column ${orderByElement.target.name} not found in the order by clause`, + ); + } + break; + case "single_column_aggregate": + throw new sdk.NotSupported("Order by aggregate is not supported."); + case "star_count_aggregate": + throw new sdk.NotSupported("Order by aggregate is not supported"); + } + } +} + +function generateAliasToSelectFromParentColumn( + parentColumn: sql.Column, +): string { + return `_subquery_parent_${parentColumn.name}`; +} + +/** + * Parses a `nestedField` on a `column` and returns a `sql.sqlQueryContext`. + + * The `sql.sqlQueryContext` will be translated to a SQL subquery with the nested fields + * requested from the `column` + + @param {string} parentColumn - Name of the column from where nested fields are to be selected. + @returns {sql.SqlQueryContext} Returns the `SqlQueryContext` which will return a SQL query context which + will contain the selection of the nested fields, which is intended to be used a subquery. + +**/ +// TODO: Please write unit tests for this function. +function selectNestedField( + nestedField: sdk.NestedField, + parentColumn: sql.Column, +): [sql.SqlQueryContext, string] { + if (nestedField.type === "object") { + let selectFields: sql.SelectColumns = {}; + const currentAlias = generateAliasToSelectFromParentColumn(parentColumn); + Object.entries(nestedField.fields).forEach(([fieldAlias, field]) => { + selectFields[fieldAlias] = selectField(field, currentAlias); + }); + const fromClause: sql.FromClause = { + source: sql.formatColumn(parentColumn), + sourceAlias: currentAlias, + }; + return [ + { + kind: "sqlQueryContext", + select: selectFields, + selectAsValue: false, + from: fromClause, + isAggregateQuery: false, + }, + currentAlias, + ]; + } else { + let [nestedFieldCtx, sourceAlias] = selectNestedField( + nestedField.fields, + parentColumn, + ); + const fromClause: sql.FromClause = { + source: sql.formatColumn(parentColumn), + in: sourceAlias, + sourceAlias, + }; + nestedFieldCtx.from = fromClause; + nestedFieldCtx.selectAsArray = true; + return [nestedFieldCtx, sourceAlias]; + } +} + +function selectField(field: sdk.Field, fieldPrefix: string): sql.SelectColumn { + switch (field.type) { + case "column": + const column: sql.Column = { + name: field.column, + prefix: fieldPrefix, + }; + if (field.fields) { + const [nestedFieldSelectCol, _] = selectNestedField( + field.fields, + column, + ); + return nestedFieldSelectCol; + } else { + return { + kind: "column", + column, + }; + } + case "relationship": + throw new sdk.BadRequest( + "Relationships are not supported in Azure Cosmos DB for NoSQL", + ); + } +} + +function getRequestedFieldsFromObject( + objectName: string, + objectType: schema.ObjectTypeDefinition, + fromSource: string, + fields: { [k: string]: sdk.Field }, +): sql.SelectColumns { + var requestedFields: sql.SelectColumns = {}; + + Object.entries(fields).forEach(([fieldName, queryField]) => { + switch (queryField.type) { + case "column": + if (!(queryField.column in objectType.properties)) { + throw new sdk.BadRequest( + `Couldn't find field '${queryField.column}' in object type '${objectName}'`, + ); + } else { + requestedFields[fieldName] = selectField(queryField, fromSource); + } + + break; + case "relationship": + throw new sdk.NotSupported( + "Querying relationship fields are not supported.", + ); + } + }); + + return requestedFields; +} + +export function getBaseType(typeDefn: schema.TypeDefinition): string { + switch (typeDefn.type) { + case "array": + return getBaseType(typeDefn.elementType); + case "nullable": + return getBaseType(typeDefn.underlyingType); + case "named": + switch (typeDefn.kind) { + case "object": + return typeDefn.name; + case "scalar": + return typeDefn.name; + } + } +} + +function parseComparisonValue( + rootContainerAlias: string, + value: sdk.ComparisonValue, + collectionObjectProperties: schema.ObjectTypePropertiesMap, + collectionName: string, + collectionsSchema: schema.CollectionsSchema, +): sql.ComparisonValue { + switch (value.type) { + case "column": + return { + type: "column", + column: sql.visitComparisonTarget( + rootContainerAlias, + value.column, + collectionObjectProperties, + collectionName, + collectionsSchema, + ), + }; + case "scalar": + return { + type: "scalar", + value: value.value, + }; + case "variable": + return { + type: "variable", + name: value.name, + }; + } +} + +function parseExpression( + rootContainerAlias: string, + expression: sdk.Expression, + collectionObjectProperties: schema.ObjectTypePropertiesMap, + collectionObjectTypeName: string, + collectionsSchema: schema.CollectionsSchema, +): sql.WhereExpression { + switch (expression.type) { + case "and": + return { + kind: "and", + expressions: expression.expressions.map((expr) => + parseExpression( + rootContainerAlias, + expr, + collectionObjectProperties, + collectionObjectTypeName, + collectionsSchema, + ), + ), + }; + case "or": + return { + kind: "or", + expressions: expression.expressions.map((expr) => + parseExpression( + rootContainerAlias, + expr, + collectionObjectProperties, + collectionObjectTypeName, + collectionsSchema, + ), + ), + }; + case "not": + return { + kind: "not", + expression: parseExpression( + rootContainerAlias, + expression.expression, + collectionObjectProperties, + collectionObjectTypeName, + collectionsSchema, + ), + }; + case "unary_comparison_operator": + switch (expression.operator) { + case "is_null": + return { + kind: "simpleWhereExpression", + column: sql.visitComparisonTarget( + rootContainerAlias, + expression.column, + collectionObjectProperties, + collectionObjectTypeName, + collectionsSchema, + ), + operator: { + name: "is_null", + isInfix: false, + isUnary: true, + }, + }; + } + case "binary_comparison_operator": + const comparisonTarget: sql.Column = sql.visitComparisonTarget( + rootContainerAlias, + expression.column, + collectionObjectProperties, + collectionObjectTypeName, + collectionsSchema, + ); + + // write a function getBinaryComparisonOperator to get the type of the `comparisonTarget` column + // if the `comparisonTarget` contains a nested field, then we need to get the type of the nested field + + console.log("comparisonTarget: ", comparisonTarget); + const comparisonTargetType = sql.getScalarType(comparisonTarget); + + console.log("comparisonTargetType: ", comparisonTargetType); + + const scalarDbOperator = sql.getDbComparisonOperator( + comparisonTargetType, + expression.operator, + ); + return { + kind: "simpleWhereExpression", + column: comparisonTarget, + value: parseComparisonValue( + rootContainerAlias, + expression.value, + collectionObjectProperties, + collectionObjectTypeName, + collectionsSchema, + ), + operator: scalarDbOperator, + }; + + case "exists": + throw new sdk.NotSupported("EXISTS operator is not supported."); + } +} + +function parseQueryRequest( + collectionsSchema: schema.CollectionsSchema, + queryRequest: sdk.QueryRequest, +): sql.SqlQueryContext { + let isAggregateQuery = false; + + const collection: string = queryRequest.collection; + + const collectionDefinition: schema.CollectionDefinition = + collectionsSchema.collections[collection]; + + const rootContainerAlias = `root_${collection}`; + + let requestedFields: sql.SelectColumns = {}; + + if (collectionDefinition === undefined) + throw new sdk.BadRequest( + `Couldn't find collection '${collection}' in the schema.`, + ); + + if (Object.keys(queryRequest.arguments).length != 0) + throw new sdk.BadRequest("Collection arguments are not supported."); + + if (Object.keys(queryRequest.collection_relationships).length != 0) + throw new sdk.BadRequest("Collection relationships are not supported."); + + const collectionObjectBaseType = schema.getBaseNamedType( + collectionDefinition.resultType, + ); + + const collectionObjectType = + collectionsSchema.objectTypes[collectionObjectBaseType]; + + if (collectionObjectType === undefined) + throw new sdk.InternalServerError( + `Couldn't find the schema of the object type: '${collectionObjectBaseType}'`, + ); + + if ( + queryRequest.query.fields !== null && + queryRequest.query.fields !== undefined && + queryRequest.query.aggregates !== null && + queryRequest.query.aggregates !== undefined + ) { + throw new sdk.NotSupported( + "Aggregates and fields cannot be requested together.", + ); + } + + if (queryRequest.query.fields) { + requestedFields = getRequestedFieldsFromObject( + collectionObjectBaseType, + collectionObjectType, + rootContainerAlias, + queryRequest.query.fields, + ); + } + + if (queryRequest.query.aggregates) { + isAggregateQuery = true; + Object.entries(queryRequest.query.aggregates).forEach( + ([fieldName, aggregateField]) => { + switch (aggregateField.type) { + case "column_count": + if (!(aggregateField.column in collectionObjectType.properties)) { + throw new sdk.BadRequest( + `Couldn't find field '${aggregateField.column}' in object type '${collectionObjectBaseType}'`, + ); + } else { + if (aggregateField.distinct) { + requestedFields[fieldName] = { + kind: "aggregate", + column: { + name: aggregateField.column, + prefix: rootContainerAlias, + }, + aggregateFunction: "DISTINCT COUNT", + }; + } else { + requestedFields[fieldName] = { + kind: "aggregate", + column: { + name: aggregateField.column, + prefix: rootContainerAlias, + }, + aggregateFunction: "COUNT", + }; + } + } + break; + case "single_column": + if (!(aggregateField.column in collectionObjectType.properties)) { + throw new sdk.BadRequest( + `Couldn't find field '${aggregateField.column}' in object type '${collectionObjectType}'`, + ); + } else { + requestedFields[fieldName] = { + kind: "aggregate", + column: { + name: aggregateField.column, + prefix: rootContainerAlias, + }, + + aggregateFunction: aggregateField.function, + }; + } + break; + case "star_count": + requestedFields[fieldName] = { + kind: "aggregate", + column: { + name: "*", + prefix: rootContainerAlias, + }, + aggregateFunction: "COUNT", + }; + break; + } + }, + ); + } + + let fromClause: sql.FromClause = { + source: collection, + sourceAlias: rootContainerAlias, + }; + + let sqlGenCtx: sql.SqlQueryContext = { + kind: "sqlQueryContext", + select: requestedFields, + from: fromClause, + isAggregateQuery, + selectAsValue: false, + }; + + if (queryRequest.query.limit != null) { + if (queryRequest.query.offset != null) { + sqlGenCtx.offset = queryRequest.query.offset; + } else { + // The Azure Cosmos DB for NoSQL SQL syntax always requires an + // offset with the limit clause, so if an offset is not + // provided, then assume the offset to be 0. + sqlGenCtx.offset = 0; + } + sqlGenCtx.limit = queryRequest.query.limit; + } + + if ( + queryRequest.query.order_by != null && + queryRequest.query.order_by != undefined + ) { + validateOrderBy(queryRequest.query.order_by, collectionObjectType); + sqlGenCtx.orderBy = queryRequest.query.order_by; + } + + if (queryRequest.query.predicate) { + const predicate = parseExpression( + rootContainerAlias, + queryRequest.query.predicate, + collectionObjectType.properties, + collectionObjectBaseType, + collectionsSchema, + ); + + sqlGenCtx.predicate = predicate; + } + + return sqlGenCtx; +} + +export async function executeQuery( + queryRequest: sdk.QueryRequest, + collectionsSchema: schema.CollectionsSchema, + dbClient: Database, +): Promise { + const collection: string = queryRequest.collection; + + const collectionDefinition: schema.CollectionDefinition = + collectionsSchema.collections[collection]; + + if (collectionDefinition === undefined) + throw new sdk.BadRequest( + `Couldn't find collection '${collection}' in the schema.`, + ); + + const dbContainer = dbClient.container(collection); + + if (dbContainer === undefined || dbContainer == null) + throw new sdk.InternalServerError( + `Couldn't find the container '${collection}' in the database.`, + ); + + const sqlGenCtx: sql.SqlQueryContext = parseQueryRequest( + collectionsSchema, + queryRequest, + ); + + const sqlQuery = sql.generateSqlQuerySpec( + sqlGenCtx, + collection, + queryRequest.variables, + ); + + const queryResponse = await runSQLQuery<{ [k: string]: unknown }>( + sqlQuery, + dbContainer, + ); + + let rowSet: sdk.RowSet = {}; + + if (sqlGenCtx.isAggregateQuery) { + rowSet.aggregates = queryResponse[0]; + } else { + rowSet.rows = queryResponse; + } + + // FIXME: When we support variables, we will need to run the query against the variables and return + // multiple row sets. + return [rowSet]; +} diff --git a/src/connector/schema.ts b/src/connector/schema.ts new file mode 100644 index 0000000..a6e3ab8 --- /dev/null +++ b/src/connector/schema.ts @@ -0,0 +1,494 @@ +import * as sdk from "@hasura/ndc-sdk-typescript"; +import { mapObjectValues } from "../utils"; +import { ScalarType } from "@hasura/ndc-sdk-typescript"; + +export type CollectionsSchema = { + collections: CollectionDefinitions; + objectTypes: ObjectTypeDefinitions; + scalarTypes: ScalarTypeDefinitions; +}; + +export type CollectionDefinitions = { + [collectionName: string]: CollectionDefinition; +}; + +export type CollectionDefinition = { + description: string | null; + arguments: ArgumentDefinition[]; + resultType: TypeDefinition; +}; + +export type ArgumentDefinition = { + argumentName: string; + description: string | null; + type: TypeDefinition; +}; + +export type ObjectTypeDefinitions = { + [objectTypeName: string]: ObjectTypeDefinition; +}; + +export type ObjectTypePropertiesMap = { + [propertyName: string]: ObjectPropertyDefinition; +}; + +export type ObjectTypeDefinition = { + description: string | null; + properties: ObjectTypePropertiesMap; +}; + +export type ObjectPropertyDefinition = { + propertyName: string; + description: string | null; + type: TypeDefinition; +}; + +export type ScalarTypeDefinitions = { + [scalarTypeName: string]: ScalarTypeDefinition; +}; + +export type ScalarTypeDefinition = BuiltInScalarTypeDefinition; // Empty object, for now + +export type TypeDefinition = + | ArrayTypeDefinition + | NullableTypeDefinition + | NamedTypeDefinition; + +export type ArrayTypeDefinition = { + type: "array"; + elementType: TypeDefinition; +}; + +export type NullableTypeDefinition = { + type: "nullable"; + underlyingType: TypeDefinition; +}; + +export type NamedTypeDefinition = + | NamedObjectTypeDefinition + | NamedScalarTypeDefinition; + +export type NamedObjectTypeDefinition = { + type: "named"; + name: string; + kind: "object"; +}; + +export type NamedScalarTypeDefinition = + | CustomNamedScalarTypeDefinition + | BuiltInScalarTypeDefinition; + +export type BuiltInScalarTypeDefinition = + | StringScalarTypeDefinition + | BooleanScalarTypeDefinition + | IntegerScalarTypeDefinition + | NumberScalarTypeDefinition + | DateTimeScalarTypeDefinition; + +export type CustomNamedScalarTypeDefinition = { + type: "named"; + name: string; + kind: "scalar"; +}; + +export type StringScalarTypeDefinition = { + type: "named"; + name: BuiltInScalarTypeName.String; + kind: "scalar"; + literalValue?: string; +}; + +export type NumberScalarTypeDefinition = { + type: "named"; + name: BuiltInScalarTypeName.Number; + kind: "scalar"; + literalValue?: number; +}; + +export type BooleanScalarTypeDefinition = { + type: "named"; + name: BuiltInScalarTypeName.Boolean; + kind: "scalar"; + literalValue?: boolean; +}; + +export type DateTimeScalarTypeDefinition = { + type: "named"; + name: BuiltInScalarTypeName.DateTime; + kind: "scalar"; +}; + +export type IntegerScalarTypeDefinition = { + type: "named"; + name: BuiltInScalarTypeName.Integer; + kind: "scalar"; +}; + +export enum BuiltInScalarTypeName { + String = "String", + Number = "Number", + Boolean = "Boolean", + DateTime = "DateTime", + Integer = "Integer", +} + +export type ScalarTypes = { + [k: string]: ScalarType; +}; + +export type ScalarOperatorMappings = { + [k: string]: string; +}; + +export const scalarTypes: ScalarTypes = { + Integer: { + aggregate_functions: { + count: { + result_type: { + type: "named", + name: BuiltInScalarTypeName.Integer, + }, + }, + sum: { + result_type: { + type: "named", + name: BuiltInScalarTypeName.Integer, + }, + }, + avg: { + result_type: { + type: "named", + name: BuiltInScalarTypeName.Integer, + }, + }, + min: { + result_type: { + type: "named", + name: BuiltInScalarTypeName.Integer, + }, + }, + max: { + result_type: { + type: "named", + name: BuiltInScalarTypeName.Integer, + }, + }, + }, + comparison_operators: { + eq: { + type: "equal", + }, + neq: { + type: "custom", + argument_type: { + type: "named", + name: "Integer", + }, + }, + gt: { + type: "custom", + argument_type: { + type: "named", + name: "Integer", + }, + }, + lt: { + type: "custom", + argument_type: { + type: "named", + name: "Integer", + }, + }, + gte: { + type: "custom", + argument_type: { + type: "named", + name: "Integer", + }, + }, + lte: { + type: "custom", + argument_type: { + type: "named", + name: "Integer", + }, + }, + }, + }, + Number: { + aggregate_functions: { + count: { + result_type: { + type: "named", + name: BuiltInScalarTypeName.Number, + }, + }, + sum: { + result_type: { + type: "named", + name: BuiltInScalarTypeName.Number, + }, + }, + avg: { + result_type: { + type: "named", + name: BuiltInScalarTypeName.Number, + }, + }, + min: { + result_type: { + type: "named", + name: BuiltInScalarTypeName.Number, + }, + }, + max: { + result_type: { + type: "named", + name: BuiltInScalarTypeName.Number, + }, + }, + }, + comparison_operators: { + eq: { + type: "equal", + }, + neq: { + type: "custom", + argument_type: { + type: "named", + name: "Number", + }, + }, + gt: { + type: "custom", + argument_type: { + type: "named", + name: "Number", + }, + }, + lt: { + type: "custom", + argument_type: { + type: "named", + name: "Number", + }, + }, + gte: { + type: "custom", + argument_type: { + type: "named", + name: "Number", + }, + }, + lte: { + type: "custom", + argument_type: { + type: "named", + name: "Number", + }, + }, + }, + }, + Boolean: { + aggregate_functions: { + bool_and: { + result_type: { + type: "named", + name: BuiltInScalarTypeName.Boolean, + }, + }, + bool_or: { + result_type: { + type: "named", + name: BuiltInScalarTypeName.Boolean, + }, + }, + bool_not: { + result_type: { + type: "named", + name: BuiltInScalarTypeName.Boolean, + }, + }, + }, + comparison_operators: { + eq: { + type: "equal", + }, + neq: { + type: "custom", + argument_type: { + type: "named", + name: "Boolean", + }, + }, + }, + }, + String: { + aggregate_functions: {}, + comparison_operators: { + eq: { + type: "equal", + }, + neq: { + type: "custom", + argument_type: { + type: "named", + name: "String", + }, + }, + gt: { + type: "custom", + argument_type: { + type: "named", + name: "String", + }, + }, + lt: { + type: "custom", + argument_type: { + type: "named", + name: "String", + }, + }, + gte: { + type: "custom", + argument_type: { + type: "named", + name: "String", + }, + }, + lte: { + type: "custom", + argument_type: { + type: "named", + name: "String", + }, + }, + contains: { + type: "custom", + argument_type: { + type: "named", + name: "String", + }, + }, + endswith: { + type: "custom", + argument_type: { + type: "named", + name: "String", + }, + }, + regexmatch: { + type: "custom", + argument_type: { + type: "named", + name: "String", + }, + }, + startswith: { + type: "custom", + argument_type: { + type: "named", + name: "String", + }, + }, + }, + }, +}; + +export function getJSONScalarTypes(): ScalarTypeDefinitions { + var scalarTypeDefinitions: ScalarTypeDefinitions = {}; + scalarTypeDefinitions["Integer"] = { + type: "named", + name: BuiltInScalarTypeName.Integer, + kind: "scalar", + }; + scalarTypeDefinitions["Number"] = { + type: "named", + name: BuiltInScalarTypeName.Number, + kind: "scalar", + }; + scalarTypeDefinitions["Boolean"] = { + type: "named", + name: BuiltInScalarTypeName.Boolean, + kind: "scalar", + }; + scalarTypeDefinitions["String"] = { + type: "named", + name: BuiltInScalarTypeName.String, + kind: "scalar", + }; + + return scalarTypeDefinitions; +} + +export function getNdcSchemaResponse( + collectionsSchema: CollectionsSchema, +): sdk.SchemaResponse { + const collections = Object.entries(collectionsSchema.collections); + + var collectionInfos = collections.map(([collectionName, collectionInfo]) => { + return { + name: collectionName, + description: null, + arguments: {}, + type: getBaseNamedType(collectionInfo.resultType), + uniqueness_constraints: {}, + foreign_keys: {}, + }; + }); + + const objectTypes = mapObjectValues( + collectionsSchema.objectTypes, + (objDef) => { + return { + fields: Object.fromEntries( + Object.values(objDef.properties).map((propDef) => { + const objField: sdk.ObjectField = { + type: convertTypeReferenceToSdkType(propDef.type), + description: null, + }; + return [propDef.propertyName, objField]; + }), + ), + ...(objDef.description ? { description: objDef.description } : {}), + }; + }, + ); + + return { + functions: [], + procedures: [], + collections: collectionInfos, + object_types: objectTypes, + scalar_types: scalarTypes, + }; +} + +function convertTypeReferenceToSdkType(typeRef: TypeDefinition): sdk.Type { + switch (typeRef.type) { + case "array": + return { + type: "array", + element_type: convertTypeReferenceToSdkType(typeRef.elementType), + }; + case "nullable": + return { + type: "nullable", + underlying_type: convertTypeReferenceToSdkType(typeRef.underlyingType), + }; + case "named": + return { type: "named", name: typeRef.name }; + } +} + +export function getBaseNamedType(typeRef: TypeDefinition): string { + switch (typeRef.type) { + case "array": + return getBaseNamedType(typeRef.elementType); + case "nullable": + return getBaseNamedType(typeRef.underlyingType); + case "named": + return typeRef.name; + } +} diff --git a/src/connector/sql/runSql.ts b/src/connector/sql/runSql.ts new file mode 100644 index 0000000..1fdcfc1 --- /dev/null +++ b/src/connector/sql/runSql.ts @@ -0,0 +1,50 @@ +// Function that accepts a SQL query and returns the result + +import { Container } from "@azure/cosmos"; +import { constructCosmosDbClient } from "../db/cosmosDb"; +import { Command } from "commander"; +import * as fs from "fs-extra"; + +// Function that accepts an arbitrary SQL query and returns the result +export async function runSQLQuery(sql: string, container: Container) { + const sqlQuerySpec = { + query: sql, + }; + + const result = await container.items + .query(sqlQuerySpec) + .fetchAll() + .catch((err) => { + console.error(err); + throw err; + }); + + console.log(JSON.stringify(result.resources, null, 2)); +} + +async function executeSqlFromFile(filePath: string, containerName: string) { + try { + const sqlQuery = await fs.readFile(filePath, "utf8"); + + let db = constructCosmosDbClient().dbClient; + const container = db.container(containerName); + + await runSQLQuery(sqlQuery, container); + } catch (err) { + console.error("Error running SQL from file:", err); + } +} + +const program = new Command(); + +program + .requiredOption( + "--container ", + "The name of the container to run the SQL in", + ) + .requiredOption("--file ", "The location of the SQL file to run") + .parse(process.argv); + +const options = program.opts(); + +executeSqlFromFile(options.file, options.container); diff --git a/src/connector/sql/sqlGeneration.ts b/src/connector/sql/sqlGeneration.ts new file mode 100644 index 0000000..27ef17c --- /dev/null +++ b/src/connector/sql/sqlGeneration.ts @@ -0,0 +1,1340 @@ +import * as sdk from "@hasura/ndc-sdk-typescript"; +import * as cosmos from "@azure/cosmos"; +import { SqlQuerySpec } from "@azure/cosmos"; +import * as schema from "../schema"; + +export type Column = { + name: string; + prefix: string; + type?: schema.TypeDefinition; // TODO(KC): Modify this to not be optional + nestedField?: NestedField; +}; + +export type SelectContainerColumn = { + kind: "column"; + column: Column; +}; + +export type SelectAggregate = { + kind: "aggregate"; + column: Column; + aggregateFunction: string; +}; + +export type SelectColumn = + | SelectContainerColumn + | SelectAggregate + | SqlQueryContext; + +type NestedObjectField = { + kind: "object"; + field: string; + + nestedField: NestedField; +}; + +type NestedArrayField = { + kind: "array"; + nestedField: NestedField; +}; + +type NestedScalarField = { + field: string; + type: string; + kind: "scalar"; +}; + +type NestedField = NestedObjectField | NestedArrayField | NestedScalarField; + +export type SimpleWhereExpression = { + kind: "simpleWhereExpression"; + column: Column; + operator: ComparisonScalarDbOperator; + // When value is undefined, it means that the operator is unary + value?: ComparisonValue | undefined; +}; + +export type AndWhereExpression = { + kind: "and"; + expressions: WhereExpression[]; +}; + +export type OrWhereExpression = { + kind: "or"; + expressions: WhereExpression[]; +}; + +export type NotWhereExpression = { + kind: "not"; + expression: WhereExpression; +}; + +export type WhereExpression = + | SimpleWhereExpression + | AndWhereExpression + | OrWhereExpression + | NotWhereExpression; + +/* + The key represents the alias of the request field and the + value represents the value to be selected from the container. +*/ +export type SelectColumns = { + [alias: string]: SelectColumn; +}; + +export type QueryVariable = { + [k: string]: unknown; +}; + +export type QueryVariables = QueryVariable[] | null | undefined; + +/* + Type to track the parameters used in the SQL query. + */ +type SqlParameters = { + [column: string]: any[]; +}; + +export type FromClause = { + source: string; + sourceAlias: string; + in?: string; +}; + +export type ContainerExpression = { + kind: "containerExpression"; + containerExpression: string; +}; + +export type SqlExpression = { + kind: "sqlExpression"; + sqlExpression: SqlQueryContext; +}; + +export type ArrayJoinTarget = ContainerExpression | SqlExpression; + +export type ArrayJoinClause = { + type: "array"; + joinIdentifier: string; + arrayJoinTarget: ArrayJoinTarget; +}; + +export type SubqueryJoinClause = { + type: "subquery"; + from: string; + subQuery: SqlQueryContext; + subQueryAs: string; +}; + +export type JoinClause = ArrayJoinClause | SubqueryJoinClause; + +export type ComparisonScalarDbOperator = { + name: string; + isInfix: boolean; + isUnary: boolean; +}; + +type AggregateScalarDbOperator = { + operator: string; + resultType: string; +}; + +// Defines how the NDC's scalar operators map to the DB operators +type ScalarDBOperatorMappings = { + comparison: { + [operatorName: string]: ComparisonScalarDbOperator; + }; + aggregate?: + | { + [operatorName: string]: AggregateScalarDbOperator; + } + | undefined; +}; + +type ScalarOperatorMappings = { + [scalarTypeName: string]: ScalarDBOperatorMappings; +}; + +export const scalarComparisonOperatorMappings: ScalarOperatorMappings = { + Integer: { + comparison: { + is_null: { + name: "IS_NULL", + isInfix: false, + isUnary: true, + }, + eq: { + name: "=", + isInfix: true, + isUnary: false, + }, + neq: { + name: "!=", + isInfix: true, + isUnary: false, + }, + gt: { + name: ">", + isInfix: true, + isUnary: false, + }, + lt: { + name: "<", + isInfix: true, + isUnary: false, + }, + gte: { + name: ">=", + isInfix: true, + isUnary: false, + }, + lte: { + name: "<=", + isInfix: true, + isUnary: false, + }, + }, + aggregate: { + count: { + operator: "count", + resultType: "Integer", + }, + sum: { + operator: "sum", + resultType: "Integer", + }, + avg: { + operator: "sum", + resultType: "Number", + }, + min: { + operator: "sum", + resultType: "Integer", + }, + max: { + operator: "sum", + resultType: "Integer", + }, + }, + }, + Number: { + comparison: { + is_null: { + name: "IS_NULL", + isInfix: false, + isUnary: true, + }, + + eq: { + name: "=", + isInfix: true, + isUnary: false, + }, + neq: { + name: "!=", + isInfix: true, + isUnary: false, + }, + gt: { + name: ">", + isInfix: true, + isUnary: false, + }, + lt: { + name: "<", + isInfix: true, + isUnary: false, + }, + gte: { + name: ">=", + isInfix: true, + isUnary: false, + }, + lte: { + name: "<=", + isInfix: true, + isUnary: false, + }, + }, + aggregate: { + count: { + operator: "count", + resultType: "Integer", + }, + sum: { + operator: "sum", + resultType: "Number", + }, + avg: { + operator: "sum", + resultType: "Number", + }, + min: { + operator: "sum", + resultType: "Number", + }, + max: { + operator: "sum", + resultType: "Number", + }, + }, + }, + Boolean: { + comparison: { + is_null: { + name: "IS_NULL", + isInfix: false, + isUnary: true, + }, + + eq: { + name: "=", + isInfix: true, + isUnary: false, + }, + neq: { + name: "!=", + isInfix: true, + isUnary: false, + }, + }, + aggregate: { + bool_and: { + operator: "bool_and", + resultType: "Boolean", + }, + bool_or: { + operator: "bool_or", + resultType: "Boolean", + }, + bool_not: { + operator: "bool_or", + resultType: "Boolean", + }, + }, + }, + String: { + comparison: { + is_null: { + name: "IS_NULL", + isInfix: false, + isUnary: true, + }, + + eq: { + name: "=", + isInfix: true, + isUnary: false, + }, + neq: { + name: "!=", + isInfix: true, + isUnary: false, + }, + gt: { + name: ">", + isInfix: true, + isUnary: false, + }, + lt: { + name: "<", + isInfix: true, + isUnary: false, + }, + gte: { + name: ">=", + isInfix: true, + isUnary: false, + }, + lte: { + name: "<=", + isInfix: true, + isUnary: false, + }, + contains: { + name: "CONTAINS", + isInfix: false, + isUnary: false, + }, + endswith: { + name: "ENDSWITH", + isInfix: false, + isUnary: false, + }, + regexmatch: { + name: "REGEXMATCH", + isInfix: false, + isUnary: false, + }, + startswith: { + name: "STARTSWITH", + isInfix: false, + isUnary: false, + }, + }, + }, +}; + +export function getScalarType(column: Column): string { + if (column.nestedField) { + return getNestedScalarType(column.nestedField); + } else { + if (column.type === undefined) { + throw new sdk.BadRequest(`Couldn't find type of column: ${column.name}`); + } else { + switch (column.type.type) { + case "array": + throw new sdk.BadRequest( + `Expected column ${column.name} to be a scalar type, but found array type`, + ); + case "named": + if (column.type.kind === "object") { + throw new sdk.BadRequest( + `Expected column ${column.name} to be a scalar type, but found object type`, + ); + } else { + return column.type.name; + } + case "nullable": + return getScalarType({ + name: column.name, + prefix: column.prefix, + type: column.type.underlyingType, + }); + } + } + } +} + +function getNestedScalarType(nestedField: NestedField): string { + switch (nestedField.kind) { + case "scalar": + return nestedField.type; + case "object": + return getNestedScalarType(nestedField.nestedField); + case "array": + return getNestedScalarType(nestedField.nestedField); + } +} + +export function getDbComparisonOperator( + scalarTypeName: string, + operator: string, +): ComparisonScalarDbOperator { + const scalarOperators = scalarComparisonOperatorMappings[scalarTypeName]; + + console.log("scalarOperators", scalarOperators, scalarTypeName); + + if (scalarOperators === undefined || scalarOperators === null) { + throw new sdk.BadRequest( + `Couldn't find scalar type: ${scalarTypeName} in the schema`, + ); + } else { + const scalarDbOperator = scalarOperators.comparison[operator]; + + if (scalarDbOperator) { + return scalarDbOperator; + } else { + throw new sdk.BadRequest( + `Comparison Operator ${operator} is not supported on type ${scalarTypeName}`, + ); + } + } +} + +export type ComparisonTarget = + | { + type: "column"; + /** + * The name of the column + */ + name: string; + } + | { + type: "root_collection_column"; + /** + * The name of the column + */ + name: string; + }; + +export type ComparisonValue = + | { + type: "column"; + column: Column; + } + | { + type: "scalar"; + value: unknown; + } + | { + type: "variable"; + name: string; + }; + +export type Expression = + | { + type: "and"; + expressions: Expression[]; + } + | { + type: "or"; + expressions: Expression[]; + } + | { + type: "not"; + expression: Expression; + } + | { + type: "unary_comparison_operator"; + column: string; + dbOperator: ComparisonScalarDbOperator; + } + | { + type: "binary_comparison_operator"; + column: string; + value: ComparisonValue; + dbOperator: ComparisonScalarDbOperator; + }; + +export type SqlQueryContext = { + kind: "sqlQueryContext"; + select: SelectColumns; + /* Set to `true` to prevent the wrapping of the results into another JSON object. */ + selectAsValue: boolean; + from?: FromClause | null; + join?: JoinClause[] | null; + predicate?: WhereExpression | null; + offset?: number | null; + limit?: number | null; + orderBy?: sdk.OrderBy | null; + isAggregateQuery: boolean; + selectAsArray?: boolean | undefined; +}; + +type VariablesMappings = { + /* + The variableTarget will be the name of the column + which gets the value of the variable + */ + [variableTarget: string]: string; +}; + +function formatJoinClause(joinClause: JoinClause): string { + if (joinClause.type === "array") { + let joinTarget = + joinClause.arrayJoinTarget.kind === "containerExpression" + ? joinClause.arrayJoinTarget.containerExpression + : constructSqlQuery( + joinClause.arrayJoinTarget.sqlExpression, + joinClause.joinIdentifier, + null, + ); + + return `${joinClause.joinIdentifier} in (${joinTarget})`; + } else { + return `(${constructSqlQuery(joinClause.subQuery, joinClause.from, null).query}) ${joinClause.subQueryAs}`; + } +} + +function formatFromClause(fromClause: FromClause): string { + if (fromClause.in !== undefined) { + return `${fromClause.in} IN ${fromClause.source}`; + } else { + return `${fromClause.source} ${fromClause.sourceAlias}`; + } +} + +/** Constructs a SQL query from the given `sqlQueryContext` + * @param sqlQueryCtx - `SqlQueryContext` which contains the data required to generate the SQL query. + * @param source - `source` to run the query on. Note that, the source can be a container or a nested field of a document of a container. + * @param queryVariables - values of the variables provided with the request. + + */ +export function constructSqlQuery( + sqlQueryCtx: SqlQueryContext, + source: string, + queryVariables: QueryVariables, +): cosmos.SqlQuerySpec { + let selectColumns = formatSelectColumns(sqlQueryCtx.select); + + let fromClause = + sqlQueryCtx.from === null || sqlQueryCtx.from === undefined + ? null + : formatFromClause(sqlQueryCtx.from); + + let whereClause = null; + let predicateParameters: SqlParameters = {}; + let utilisedVariables: VariablesMappings = {}; // This will be used to add the join mappings to the where expression. + + let parameters: cosmos.SqlParameter[] = []; + + if (sqlQueryCtx.predicate !== null && sqlQueryCtx.predicate !== undefined) { + const whereExp = translateWhereExpression( + // Translate the where expression to SQL + sqlQueryCtx.predicate, + predicateParameters, + utilisedVariables, + ); + + whereClause = `WHERE ${whereExp}`; + + parameters = serializeSqlParameters(predicateParameters); + + if (Object.keys(utilisedVariables).length > 0) { + if (queryVariables === null || queryVariables === undefined) { + throw new sdk.BadRequest( + `The variables (${JSON.stringify(Object.values(utilisedVariables))}) were referenced in the variable, but their values were not provided`, + ); + } else { + parameters.push({ + name: "@vars", + value: queryVariables as cosmos.JSONValue, + }); + } + } + } + + let joinClause = null; + + if (Object.keys(utilisedVariables).length > 0) { + let variablesJoinTarget: ArrayJoinTarget = { + kind: "containerExpression", + containerExpression: "SELECT VALUE @vars", + }; + let joinExp: JoinClause = { + type: "array", + joinIdentifier: "vars", + arrayJoinTarget: variablesJoinTarget, + }; + joinClause = `JOIN ${formatJoinClause(joinExp)}`; + } + + let orderByClause = null; + + if (sqlQueryCtx.orderBy && sqlQueryCtx.orderBy.elements.length > 0) { + orderByClause = visitOrderByElements(sqlQueryCtx.orderBy.elements, source); + } + + let offsetClause = null; + + if (sqlQueryCtx.offset != undefined && sqlQueryCtx.offset != null) { + offsetClause = `${sqlQueryCtx.offset}`; + } + + let limitClause = null; + + if (sqlQueryCtx.limit != undefined && sqlQueryCtx.limit != null) { + limitClause = `${sqlQueryCtx.limit}`; + } + + let query = `SELECT ${sqlQueryCtx.selectAsValue ? "VALUE" : ""} ${selectColumns} + ${fromClause ? "FROM " + fromClause : ""} + ${joinClause ?? ""} + ${whereClause ?? ""} + ${orderByClause ? "ORDER BY " + orderByClause : ""} + ${offsetClause ? "OFFSET " + offsetClause : ""} + ${limitClause ? "LIMIT " + limitClause : ""}`; + + console.log("Query", query); + + return { + query, + parameters, + }; +} + +export function generateSqlQuerySpec( + sqlGenCtx: SqlQueryContext, + containerName: string, + queryVariables: QueryVariables, +): SqlQuerySpec { + return constructSqlQuery(sqlGenCtx, `root_${containerName}`, queryVariables); +} + +export function formatColumn(column: Column) { + return `${column.prefix}.${column.name}`; +} + +function formatSelectColumns(fieldsToSelect: SelectColumns): string { + if (Object.keys(fieldsToSelect).length === 0) { + return "VALUE {}"; + } + return Object.entries(fieldsToSelect) + .map(([alias, selectColumn]) => { + switch (selectColumn.kind) { + case "column": + return `${formatColumn(selectColumn.column)} ?? null as ${alias}`; + case "sqlQueryContext": + let query = constructSqlQuery(selectColumn, alias, null).query.trim(); + if (selectColumn.selectAsArray) { + return `(ARRAY(${query})) as ${alias}`; + } else { + return `(${query}) as ${alias}`; + } + case "aggregate": + return `${selectColumn.aggregateFunction} (${formatColumn(selectColumn.column)}) as ${alias} `; + } + }) + .join(","); +} + +/* + Traverses over the order by elements and generates the ORDER BY clause. + NOTE that this function expects the `values` parameter to be a non-empty list. + */ +function visitOrderByElements( + values: sdk.OrderByElement[], + containerAlias: string, +): string { + if (values.length === 0) { + throw new sdk.InternalServerError( + "visit_order_by_elements called with an empty list", + ); + } + return values + .map((element) => visitOrderByElement(element, containerAlias)) + .join(", "); +} + +function visitOrderByElement( + value: sdk.OrderByElement, + containerAlias: string, +): string { + const direction = value.order_direction === "asc" ? "ASC" : "DESC"; + + switch (value.target.type) { + case "column": + if (value.target.path.length > 0) { + throw new sdk.NotSupported( + "Relationships are not supported in order_by.", + ); + } else { + return `${containerAlias}.${value.target.name} ${direction} `; + } + + case "single_column_aggregate": + throw new sdk.NotSupported("Order by aggregate is not supported"); + + case "star_count_aggregate": + throw new sdk.NotSupported("Order by aggregate is not supported"); + } +} + +/* + Wraps the expression in parantheses to avoid generating SQL with wrong operator precedence. + */ +function visitExpressionWithParentheses( + parameters: SqlParameters, + variables: VariablesMappings, + expression: Expression, + containerAlias: string, +): string { + return `(${visitExpression(parameters, variables, expression, containerAlias)})`; +} + +function visitExpression( + parameters: SqlParameters, + variables: VariablesMappings, + expression: Expression, + containerAlias: string, +): string { + switch (expression.type) { + case "and": + if (expression.expressions.length > 0) { + return expression.expressions + .map((expr) => + visitExpressionWithParentheses( + parameters, + variables, + expr, + containerAlias, + ), + ) + .join(" AND "); + } else { + return "true"; + } + + case "or": + if (expression.expressions.length > 0) { + return expression.expressions + .map((expr) => + visitExpressionWithParentheses( + parameters, + variables, + expr, + containerAlias, + ), + ) + .join(" OR "); + } else { + return "false"; + } + + case "not": + return `NOT ${visitExpressionWithParentheses(parameters, variables, expression.expression, containerAlias)} `; + + case "unary_comparison_operator": + let unaryPredicate = ""; + switch (expression.dbOperator.name) { + case "is_null": + unaryPredicate = `IS_NULL(${containerAlias}.${expression.column})`; + } + return unaryPredicate; + + case "binary_comparison_operator": + const comparisonValue = visitComparisonValue( + parameters, + variables, + expression.value, + expression.column, + containerAlias, + ); + + if (expression.dbOperator.isInfix) { + return `${containerAlias}.${expression.column} ${expression.dbOperator.name} ${comparisonValue}`; + } else { + return `${expression.dbOperator.name}(${containerAlias}.${expression.column}, ${comparisonValue}) `; + } + + default: + throw new sdk.InternalServerError("Unknown expression type"); + } +} + +function visitNestedField( + fieldNames: string[], + parentFieldType: schema.TypeDefinition, + parentObjectName: string, + collectionsSchema: schema.CollectionsSchema, +): NestedField | undefined { + if (fieldNames.length === 0) { + throw new sdk.BadRequest("Field path cannot be empty"); + } else { + switch (parentFieldType.type) { + case "array": + return { + kind: "array", + nestedField: visitNestedField( + fieldNames, + parentFieldType.elementType, + parentObjectName, + collectionsSchema, + ), + } as NestedArrayField; + case "nullable": + return visitNestedField( + fieldNames, + parentFieldType.underlyingType, + parentObjectName, + collectionsSchema, + ); + case "named": + switch (parentFieldType.kind) { + case "object": + const [currentFieldName, ...remainingFields] = fieldNames; + + const parentObjectType: schema.ObjectTypeDefinition = + collectionsSchema.objectTypes[parentFieldType.name]; + + if (parentObjectType === undefined) { + throw new sdk.BadRequest( + `Could not find the object ${parentFieldType.name} in the schema`, + ); + } + console.log( + "Looking for field", + currentFieldName, + "in object", + parentObjectType, + ); + const currentFieldDefn = + parentObjectType.properties[currentFieldName]; + + if (currentFieldDefn === undefined || currentFieldDefn === null) { + throw new sdk.NotSupported( + `Field ${currentFieldName} does not exist in the object ${parentObjectName}`, + ); + } else { + switch (currentFieldDefn.type.type) { + case "named": + switch (currentFieldDefn.type.kind) { + case "object": + return { + kind: "object", + field: currentFieldName, + nestedField: visitNestedField( + remainingFields, + currentFieldDefn.type, + currentFieldDefn.type.name, + collectionsSchema, + ), + } as NestedObjectField; + case "scalar": + if (remainingFields.length === 0) { + return { + kind: "scalar", + field: fieldNames[0], + type: currentFieldDefn.type.name, + } as NestedScalarField; + } else { + throw new sdk.BadRequest( + `Found the type of the field ${currentFieldName} to be a scalar, but scalar fields can only be the last element in the field path`, + ); + } + } + case "array": + return { + kind: "array", + nestedField: visitNestedField( + remainingFields, + currentFieldDefn.type.elementType, + parentObjectName, + collectionsSchema, + ), + } as NestedArrayField; + case "nullable": + return visitNestedField( + remainingFields, + currentFieldDefn.type.underlyingType, + parentObjectName, + collectionsSchema, + ); + } + } + case "scalar": + throw new sdk.BadRequest( + `Found the type of the field ${parentObjectName} to be a scalar, but scalar fields can only be the last element in the field path`, + ); + } + } + } +} + +export function visitComparisonTarget( + rootContainerAlias: string, + target: sdk.ComparisonTarget, + collectionObject: schema.ObjectTypePropertiesMap, + collectionObjectName: string, + schema: schema.CollectionsSchema, +): Column { + switch (target.type) { + case "column": + if (target.path.length > 0) { + throw new sdk.NotSupported( + "Relationship fields are not supported in predicates.", + ); + } + + let nestedField = undefined; + + let comparisonTargetType = collectionObject[target.name].type; + + if (target.field_path && target.field_path.length > 0) { + let fieldPath = target.field_path; + + nestedField = visitNestedFieldRefactored( + fieldPath, + comparisonTargetType, + collectionObjectName, + schema, + ); + + console.log("nestedField", nestedField); + } + + return { + name: target.name, + prefix: rootContainerAlias, + type: comparisonTargetType, + nestedField, + }; + case "root_collection_column": + throw new sdk.NotSupported( + "Root collection column comparison is not supported", + ); + } +} + +function visitComparisonValue( + parameters: SqlParameters, + variables: VariablesMappings, + target: ComparisonValue, + comparisonTarget: string, + containerAlias: string, +): string { + switch (target.type) { + case "scalar": + const comparisonTargetName = comparisonTarget.replace(".", "_"); + const comparisonTargetParameterValues = parameters[comparisonTargetName]; + if (comparisonTargetParameterValues != null) { + const index = comparisonTargetParameterValues.findIndex( + (element) => element === target.value, + ); + if (index !== -1) { + return `@${comparisonTargetName}_${index} `; + } else { + let newIndex = + parameters[comparisonTargetName].push(target.value) - 1; + return `@${comparisonTargetName}_${newIndex} `; + } + } else { + parameters[comparisonTargetName] = [target.value]; + return `@${comparisonTargetName}_0`; + } + + case "column": + return `${containerAlias}.${target.column}`; + + case "variable": + variables[comparisonTarget] = `vars["${target.name}"]`; + return `vars["${target.name}"]`; + } +} + +function serializeSqlParameters( + parameters: SqlParameters, +): cosmos.SqlParameter[] { + let sqlParameters: cosmos.SqlParameter[] = []; + + for (const comparisonTarget in parameters) { + const comparisonTargetValues = parameters[comparisonTarget]; + + for (let i = 0; i < comparisonTargetValues.length; i++) { + sqlParameters.push({ + name: `@${comparisonTarget}_${i}`, + value: comparisonTargetValues[i], + }); + } + } + + return sqlParameters; +} + +export function translateWhereExpression( + whereExpression: WhereExpression, + parameters: SqlParameters, + variables: VariablesMappings, +): string { + switch (whereExpression.kind) { + case "simpleWhereExpression": + return translateColumnPredicate( + whereExpression.column, + whereExpression.operator, + whereExpression.value, + parameters, + variables, + ); + + case "and": + if (whereExpression.expressions.length > 0) { + return whereExpression.expressions + .map((e) => `(${translateWhereExpression(e, parameters, variables)})`) + .join(" AND "); + } else { + return "true"; + } + + case "or": + if (whereExpression.expressions.length > 0) { + return whereExpression.expressions + .map((e) => `(${translateWhereExpression(e, parameters, variables)})`) + .join(" OR "); + } else { + return "false"; + } + + case "not": + return `(NOT (${translateWhereExpression(whereExpression.expression, parameters, variables)})) `; + } +} + +// Function to recursively build the nested query part +function buildNestedQuery( + nestedField: NestedField, + parentField: string, + arrayCounter: number, + value: ComparisonValue | undefined, + operator: ComparisonScalarDbOperator, + parameters: SqlParameters, + variables: VariablesMappings, +): string { + switch (nestedField.kind) { + case "array": + const nestedFieldAlias = `array_element_${arrayCounter++}`; + return `EXISTS( + SELECT 1 + FROM ${nestedFieldAlias} IN ${parentField} + WHERE ${buildNestedQuery(nestedField.nestedField, nestedFieldAlias, arrayCounter, value, operator, parameters, variables)})`; + + case "object": + const alias = `${parentField}.${(nestedField as NestedObjectField).field}`; + return buildNestedQuery( + nestedField.nestedField, + alias, + arrayCounter, + value, + operator, + parameters, + variables, + ); + case "scalar": + if (value === undefined) { + if (operator.isUnary) { + return `${operator.name}(${parentField}.${nestedField.field})`; + } else { + throw new sdk.InternalServerError( + "Value is undefined where a value was expected", + ); + } + } else { + const comparisonValueRef = visitComparisonValue( + parameters, + variables, + value, + nestedField.field, + parentField, + ); + + // abstract the logic for infix and prefix operators in a function to avoid code duplication + if (operator.isInfix) { + return `${parentField}.${(nestedField as NestedScalarField).field} ${operator.name} ${comparisonValueRef}`; + } else { + return `${operator.name}(${parentField}.${(nestedField as NestedScalarField).field}, ${comparisonValueRef})`; + } + } + } +} + +// Function to generate the SQL query +export function translateColumnPredicate( + column: Column, + operator: ComparisonScalarDbOperator, + value: ComparisonValue | undefined, + parameters: SqlParameters, + variables: VariablesMappings, +): string { + const { name, prefix, nestedField } = column; + + // Initial alias for the top-level field + const topLevelAlias = prefix + "." + name; + let query = ""; + let predicate = ""; + if (nestedField === undefined) { + if (value !== undefined) { + const comparisonValueRef = visitComparisonValue( + parameters, + variables, + value, + name, + prefix, + ); + if (operator.isInfix) { + predicate = `${topLevelAlias} ${operator.name} ${comparisonValueRef}`; + } else { + predicate = `${operator.name}(${topLevelAlias}, ${comparisonValueRef})`; + } + query = predicate; + } else if (operator.isUnary) { + predicate = `${operator.name}(${topLevelAlias})`; + } else { + throw new sdk.InternalServerError( + "Binary comparison operator requires a value to be provided", + ); + } + } else { + query = buildNestedQuery( + nestedField, + topLevelAlias, + 1, + value, + operator, + parameters, + variables, + ); + } + + return `${query.trim()}`; +} + +function visitNestedFieldRefactored( + fieldNames: string[], + parentFieldType: schema.TypeDefinition, + parentObjectName: string, + collectionsSchema: schema.CollectionsSchema, +): NestedField { + if (fieldNames.length === 0) { + throw new sdk.BadRequest("Field path cannot be empty"); + } + + return handleFieldType( + fieldNames, + parentFieldType, + parentObjectName, + collectionsSchema, + ); +} + +function handleFieldType( + fieldNames: string[], + fieldType: schema.TypeDefinition, + parentObjectName: string, + collectionsSchema: schema.CollectionsSchema, +): NestedField { + switch (fieldType.type) { + case "array": + return handleArrayType( + fieldNames, + fieldType, + parentObjectName, + collectionsSchema, + ); + case "nullable": + return handleNullableType( + fieldNames, + fieldType, + parentObjectName, + collectionsSchema, + ); + case "named": + return handleNamedType( + fieldNames, + fieldType, + parentObjectName, + collectionsSchema, + ); + } +} + +function handleArrayType( + fieldNames: string[], + fieldType: schema.ArrayTypeDefinition, + parentObjectName: string, + collectionsSchema: schema.CollectionsSchema, +): NestedArrayField { + return { + kind: "array", + nestedField: handleFieldType( + fieldNames, + fieldType.elementType, + parentObjectName, + collectionsSchema, + ), + }; +} + +function handleNullableType( + fieldNames: string[], + fieldType: schema.NullableTypeDefinition, + parentObjectName: string, + collectionsSchema: schema.CollectionsSchema, +): NestedField { + return handleFieldType( + fieldNames, + fieldType.underlyingType, + parentObjectName, + collectionsSchema, + ); +} + +function handleNamedType( + fieldNames: string[], + fieldType: schema.NamedTypeDefinition, + parentObjectName: string, + collectionsSchema: schema.CollectionsSchema, +): NestedField { + switch (fieldType.kind) { + case "object": + return handleObjectType( + fieldNames, + fieldType, + parentObjectName, + collectionsSchema, + ); + case "scalar": + return handleScalarType(fieldNames, fieldType); + } +} + +function handleObjectType( + fieldNames: string[], + fieldType: schema.NamedObjectTypeDefinition, + parentObjectName: string, + collectionsSchema: schema.CollectionsSchema, +): NestedField { + const [currentFieldName, ...remainingFields] = fieldNames; + const parentObjectType: schema.ObjectTypeDefinition = + collectionsSchema.objectTypes[fieldType.name]; + + if (!parentObjectType) { + throw new sdk.BadRequest( + `Could not find the object ${fieldType.name} in the schema`, + ); + } + + const currentFieldDefn = parentObjectType.properties[currentFieldName]; + + if (!currentFieldDefn) { + throw new sdk.NotSupported( + `Field ${currentFieldName} does not exist in the object ${parentObjectName}`, + ); + } + + switch (currentFieldDefn.type.type) { + case "named": + switch (currentFieldDefn.type.kind) { + case "object": + return { + kind: "object", + field: currentFieldName, + nestedField: handleFieldType( + remainingFields, + currentFieldDefn.type, + currentFieldName, + collectionsSchema, + ), + }; + case "scalar": + return handleScalarType( + [currentFieldName, ...remainingFields], + currentFieldDefn.type, + ); + } + case "array": + return { + kind: "array", + nestedField: handleFieldType( + remainingFields, + currentFieldDefn.type.elementType, + currentFieldName, + collectionsSchema, + ), + }; + case "nullable": + return handleFieldType( + remainingFields, + currentFieldDefn.type.underlyingType, + currentFieldName, + collectionsSchema, + ); + } +} + +function handleScalarType( + fieldNames: string[], + fieldType: schema.NamedScalarTypeDefinition, +): NestedScalarField { + if (fieldNames.length > 1) { + throw new sdk.BadRequest( + `Scalar field ${fieldNames[0]} cannot have nested fields`, + ); + } + + return { + kind: "scalar", + field: fieldNames[0], + type: fieldType.name, + }; +} diff --git a/src/execution.ts b/src/execution.ts deleted file mode 100644 index fcbc91f..0000000 --- a/src/execution.ts +++ /dev/null @@ -1,370 +0,0 @@ -import * as sdk from "@hasura/ndc-sdk-typescript"; -import * as schema from "./schema"; -import * as sql from "./sqlGeneration"; -import { Database } from "@azure/cosmos"; -import { runSQLQuery } from "./cosmosDb"; - - -function validateOrderBy(orderBy: sdk.OrderBy, collectionObjectType: schema.ObjectTypeDefinition) { - - for (const orderByElement of orderBy.elements) { - switch (orderByElement.target.type) { - case 'column': - if (orderByElement.target.path.length > 0) { - throw new sdk.NotSupported("Relationships references are not supported in order by.") - }; - if (!(orderByElement.target.name in collectionObjectType.properties)) { - throw new sdk.BadRequest(`Column ${orderByElement.target.name} not found in the order by clause`) - }; - break; - case 'single_column_aggregate': - throw new sdk.NotSupported('Order by aggregate is not supported.') - case 'star_count_aggregate': - throw new sdk.NotSupported('Order by aggregate is not supported') - } - } -} - -function generateAliasToSelectFromParentColumn(parentColumn: sql.Column): string { - return `_subquery_parent_${parentColumn.name}` -} - - -/** - * Parses a `nestedField` on a `column` and returns a `sql.sqlQueryContext`. - - * The `sql.sqlQueryContext` will be translated to a SQL subquery with the nested fields - * requested from the `column` - - @param {string} parentColumn - Name of the column from where nested fields are to be selected. - @returns {sql.SqlQueryContext} Returns the `SqlQueryContext` which will return a SQL query context which - will contain the selection of the nested fields, which is intended to be used a subquery. - -**/ -// TODO: Please write unit tests for this function. -function selectNestedField(nestedField: sdk.NestedField, parentColumn: sql.Column): [sql.SqlQueryContext, string] { - if (nestedField.type === "object") { - let selectFields: sql.SelectColumns = {}; - const currentAlias = generateAliasToSelectFromParentColumn(parentColumn); - Object.entries(nestedField.fields).forEach(([fieldAlias, field]) => { - selectFields[fieldAlias] = selectField(field, currentAlias); - }); - const fromClause: sql.FromClause = { - source: sql.formatColumn(parentColumn), - sourceAlias: currentAlias, - }; - return [{ - kind: 'sqlQueryContext', - select: selectFields, - selectAsValue: false, - from: fromClause, - isAggregateQuery: false, - - }, currentAlias] - } else { - let [nestedFieldCtx, sourceAlias] = selectNestedField(nestedField.fields, parentColumn); - const fromClause: sql.FromClause = { - source: sql.formatColumn(parentColumn), - in: sourceAlias, - sourceAlias - }; - nestedFieldCtx.from = fromClause; - nestedFieldCtx.selectAsArray = true; - return [nestedFieldCtx, sourceAlias]; - } -} - -function selectField(field: sdk.Field, fieldPrefix: string): sql.SelectColumn { - switch (field.type) { - case 'column': - const column = { - name: field.column, - prefix: fieldPrefix - }; - if (field.fields !== null && field.fields !== undefined) { - const [nestedFieldSelectCol, _] = selectNestedField(field.fields, column); - return nestedFieldSelectCol - } else { - return { - kind: 'column', - column - } - } - case 'relationship': - throw new sdk.BadRequest("Relationships are not supported in Azure Cosmos DB for NoSQL") - - } -} - -function getRequestedFieldsFromObject(objectName: string, objectType: schema.ObjectTypeDefinition, fromSource: string, fields: { [k: string]: sdk.Field }): sql.SelectColumns { - - var requestedFields: sql.SelectColumns = {}; - - Object.entries(fields).forEach(([fieldName, queryField]) => { - switch (queryField.type) { - case "column": - if (!(queryField.column in objectType.properties)) { - throw new sdk.BadRequest(`Couldn't find field '${queryField.column}' in object type '${objectName}'`); - } else { - requestedFields[fieldName] = selectField(queryField, fromSource); - }; - - break; - case "relationship": - throw new sdk.NotSupported('Querying relationship fields are not supported.'); - } - }) - - return requestedFields -} - -function getBaseType(typeDefn: schema.TypeDefinition): string { - switch (typeDefn.type) { - case "array": - return getBaseType(typeDefn.elementType) - case "nullable": - return getBaseType(typeDefn.underlyingType) - case "named": - switch (typeDefn.kind) { - case "object": - return typeDefn.name - case "scalar": - return typeDefn.name - } - } -} - -function parseComparisonValue(value: sdk.ComparisonValue): sql.ComparisonValue { - switch (value.type) { - case "column": - return { - "type": "column", - column: sql.visitComparisonTarget(value.column) - } - case "scalar": - return { - "type": "scalar", - value: value.value - } - case "variable": - return { - "type": "variable", - name: value.name - } - } -} - -function parseExpression(expression: sdk.Expression, collectionObjectProperties: schema.ObjectTypePropertiesMap, collectionObjectTypeName: string): sql.Expression { - switch (expression.type) { - case "and": - return { - type: "and", - expressions: expression.expressions.map(expr => parseExpression(expr, collectionObjectProperties, collectionObjectTypeName)) - } - case "or": - return { - type: "or", - expressions: expression.expressions.map(expr => parseExpression(expr, collectionObjectProperties, collectionObjectTypeName)) - } - case "not": - return { - type: "not", - expression: parseExpression(expression.expression, collectionObjectProperties, collectionObjectTypeName) - } - case "unary_comparison_operator": - switch (expression.operator) { - case "is_null": - return { - type: "unary_comparison_operator", - column: sql.visitComparisonTarget(expression.column), - operator: "is_null" - } - } - case "binary_comparison_operator": - const comparisonTarget = sql.visitComparisonTarget(expression.column); - const comparisonTargetTypeProperty = collectionObjectProperties[comparisonTarget]; - if (!comparisonTargetTypeProperty === undefined) { - throw new sdk.BadRequest(`Couldn't find column ${comparisonTarget} in object type: ${collectionObjectTypeName}`) - } - const comparisonTargetType = getBaseType(comparisonTargetTypeProperty.type); - const scalarDbOperator = sql.getDbComparisonOperator(comparisonTargetType, expression.operator); - return { - type: "binary_comparison_operator", - column: comparisonTarget, - value: parseComparisonValue(expression.value), - dbOperator: scalarDbOperator - } - - case "exists": - throw new sdk.NotSupported('EXISTS operator is not supported.') - } -} - -function parseQueryRequest(collectionsSchema: schema.CollectionsSchema, queryRequest: sdk.QueryRequest): sql.SqlQueryContext { - let isAggregateQuery = false; - - const collection: string = queryRequest.collection; - - const collectionDefinition: schema.CollectionDefinition = collectionsSchema.collections[collection]; - - const rootContainerAlias = `root_${collection}`; - - let requestedFields: sql.SelectColumns = {}; - - if (collectionDefinition === undefined) - throw new sdk.BadRequest(`Couldn't find collection '${collection}' in the schema.`) - - if (Object.keys(queryRequest.arguments).length != 0) - throw new sdk.BadRequest('Collection arguments are not supported.') - - if (Object.keys(queryRequest.collection_relationships).length != 0) - throw new sdk.BadRequest('Collection relationships are not supported.') - - const collectionObjectBaseType = schema.getBaseNamedType(collectionDefinition.resultType); - - const collectionObjectType = collectionsSchema.objectTypes[collectionObjectBaseType]; - - if (collectionObjectType === undefined) - throw new sdk.InternalServerError(`Couldn't find the schema of the object type: '${collectionObjectBaseType}'`) - - if ((queryRequest.query.fields !== null && queryRequest.query.fields !== undefined) && (queryRequest.query.aggregates !== null && queryRequest.query.aggregates !== undefined)) { - throw new sdk.NotSupported("Aggregates and fields cannot be requested together.") - } - - if ((queryRequest.query.fields !== null) && queryRequest.query.fields !== undefined) { - requestedFields = getRequestedFieldsFromObject(collectionObjectBaseType, collectionObjectType, rootContainerAlias, queryRequest.query.fields) - } - - if (queryRequest.query.aggregates !== null && queryRequest.query.aggregates !== undefined) { - isAggregateQuery = true; - Object.entries(queryRequest.query.aggregates).forEach(([fieldName, aggregateField]) => { - switch (aggregateField.type) { - case "column_count": - if (!(aggregateField.column in collectionObjectType.properties)) { - throw new sdk.BadRequest(`Couldn't find field '${aggregateField.column}' in object type '${collectionObjectBaseType}'`); - } else { - if (aggregateField.distinct) { - requestedFields[fieldName] = { - kind: 'aggregate', - column: { - name: aggregateField.column, - prefix: rootContainerAlias, - }, - aggregateFunction: 'DISTINCT COUNT' - }; - - } else { - requestedFields[fieldName] = { - kind: 'aggregate', - column: { - name: aggregateField.column, - prefix: rootContainerAlias, - }, - aggregateFunction: 'COUNT' - } - } - - } - break; - case "single_column": - if (!(aggregateField.column in collectionObjectType.properties)) { - throw new sdk.BadRequest(`Couldn't find field '${aggregateField.column}' in object type '${collectionObjectType}'`); - } else { - requestedFields[fieldName] = { - kind: 'aggregate', - column: { - name: aggregateField.column, - prefix: rootContainerAlias - }, - - aggregateFunction: aggregateField.function - } - - } - break; - case "star_count": - requestedFields[fieldName] = { - kind: 'aggregate', - column: { - name: "*", - prefix: rootContainerAlias, - }, - aggregateFunction: 'COUNT' - }; - break; - } - }) - } - - let fromClause: sql.FromClause = { - source: collection, - sourceAlias: rootContainerAlias, - }; - - let sqlGenCtx: sql.SqlQueryContext = { - kind: 'sqlQueryContext', - select: requestedFields, - from: fromClause, - isAggregateQuery, - selectAsValue: false, - - }; - - if (queryRequest.query.limit != null) { - if (queryRequest.query.offset != null) { - sqlGenCtx.offset = queryRequest.query.offset - } else { - // The Azure Cosmos DB for NoSQL SQL syntax always requires an - // offset with the limit clause, so if an offset is not - // provided, then assume the offset to be 0. - sqlGenCtx.offset = 0 - } - sqlGenCtx.limit = queryRequest.query.limit - } - - - if (queryRequest.query.order_by != null && queryRequest.query.order_by != undefined) { - validateOrderBy(queryRequest.query.order_by, collectionObjectType); - sqlGenCtx.orderBy = queryRequest.query.order_by; - } - - if (queryRequest.query.predicate) { - sqlGenCtx.predicate = parseExpression(queryRequest.query.predicate, collectionObjectType.properties, collection); - } - - return sqlGenCtx - -} - -export async function executeQuery(queryRequest: sdk.QueryRequest, collectionsSchema: schema.CollectionsSchema, dbClient: Database): Promise { - const collection: string = queryRequest.collection; - - const collectionDefinition: schema.CollectionDefinition = collectionsSchema.collections[collection]; - - if (collectionDefinition === undefined) - throw new sdk.BadRequest(`Couldn't find collection '${collection}' in the schema.`) - - - const dbContainer = dbClient.container(collection); - - if (dbContainer === undefined || dbContainer == null) - throw new sdk.InternalServerError(`Couldn't find the container '${collection}' in the database.`) - - const sqlGenCtx: sql.SqlQueryContext = parseQueryRequest(collectionsSchema, queryRequest); - - const sqlQuery = sql.generateSqlQuerySpec(sqlGenCtx, collection, queryRequest.variables, collectionsSchema); - - const queryResponse = await runSQLQuery<{ [k: string]: unknown }>(sqlQuery, dbContainer); - - let rowSet: sdk.RowSet = {}; - - if (sqlGenCtx.isAggregateQuery) { - rowSet.aggregates = queryResponse[0] - } else { - rowSet.rows = queryResponse - } - - // FIXME: When we support variables, we will need to run the query against the variables and return - // multiple row sets. - return [rowSet] -} diff --git a/src/index.ts b/src/index.ts index 0f3a3ae..3e27831 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ import * as sdk from "@hasura/ndc-sdk-typescript"; -import { createConnector } from "./connector" +import { createConnector } from "./connector/connector"; -sdk.start(createConnector()) +sdk.start(createConnector()); diff --git a/src/schema.ts b/src/schema.ts deleted file mode 100644 index 15800b9..0000000 --- a/src/schema.ts +++ /dev/null @@ -1,471 +0,0 @@ -import * as sdk from "@hasura/ndc-sdk-typescript"; -import { mapObjectValues } from "./utils"; -import { ScalarType } from "@hasura/ndc-sdk-typescript"; - -export type CollectionsSchema = { - collections: CollectionDefinitions - objectTypes: ObjectTypeDefinitions - scalarTypes: ScalarTypeDefinitions -} - -export type CollectionDefinitions = { - [collectionName: string]: CollectionDefinition -} - -export type CollectionDefinition = { - description: string | null, - arguments: ArgumentDefinition[] - resultType: TypeDefinition -} - -export type ArgumentDefinition = { - argumentName: string, - description: string | null, - type: TypeDefinition -} - -export type ObjectTypeDefinitions = { - [objectTypeName: string]: ObjectTypeDefinition -} - -export type ObjectTypePropertiesMap = { - [propertyName: string]: ObjectPropertyDefinition -} - - -export type ObjectTypeDefinition = { - description: string | null, - properties: ObjectTypePropertiesMap -} - -export type ObjectPropertyDefinition = { - propertyName: string, - description: string | null, - type: TypeDefinition, -} - -export type ScalarTypeDefinitions = { - [scalarTypeName: string]: ScalarTypeDefinition -} - -export type ScalarTypeDefinition = BuiltInScalarTypeDefinition // Empty object, for now - -export type TypeDefinition = ArrayTypeDefinition | NullableTypeDefinition | NamedTypeDefinition - -export type ArrayTypeDefinition = { - type: "array" - elementType: TypeDefinition -} - -export type NullableTypeDefinition = { - type: "nullable", - underlyingType: TypeDefinition -} - -export type NamedTypeDefinition = NamedObjectTypeDefinition | NamedScalarTypeDefinition - -export type NamedObjectTypeDefinition = { - type: "named" - name: string - kind: "object" -} - -export type NamedScalarTypeDefinition = CustomNamedScalarTypeDefinition | BuiltInScalarTypeDefinition - -export type BuiltInScalarTypeDefinition = StringScalarTypeDefinition | BooleanScalarTypeDefinition | IntegerScalarTypeDefinition | NumberScalarTypeDefinition | DateTimeScalarTypeDefinition - -export type CustomNamedScalarTypeDefinition = { - type: "named" - name: string - kind: "scalar" -} - -export type StringScalarTypeDefinition = { - type: "named" - name: BuiltInScalarTypeName.String - kind: "scalar" - literalValue?: string -} - -export type NumberScalarTypeDefinition = { - type: "named" - name: BuiltInScalarTypeName.Number - kind: "scalar" - literalValue?: number -} - -export type BooleanScalarTypeDefinition = { - type: "named" - name: BuiltInScalarTypeName.Boolean - kind: "scalar" - literalValue?: boolean -} - -export type DateTimeScalarTypeDefinition = { - type: "named" - name: BuiltInScalarTypeName.DateTime - kind: "scalar" -} - -export type IntegerScalarTypeDefinition = { - type: "named" - name: BuiltInScalarTypeName.Integer - kind: "scalar" -} - - -export enum BuiltInScalarTypeName { - String = "String", - Number = "Number", - Boolean = "Boolean", - DateTime = "DateTime", - Integer = "Integer" -} - -export type ScalarTypes = { - [k: string]: ScalarType; -}; - -export type ScalarOperatorMappings = { - [k: string]: string -}; - -export const scalarTypes: ScalarTypes = { - "Integer": { - aggregate_functions: { - "count": { - result_type: { - type: "named", - name: BuiltInScalarTypeName.Integer, - } - }, - "sum": { - result_type: { - type: "named", - name: BuiltInScalarTypeName.Integer, - } - }, - "avg": { - result_type: { - type: "named", - name: BuiltInScalarTypeName.Integer, - } - }, - "min": { - result_type: { - type: "named", - name: BuiltInScalarTypeName.Integer, - } - }, - "max": { - result_type: { - type: "named", - name: BuiltInScalarTypeName.Integer, - } - } - }, - comparison_operators: { - eq: { - type: "equal" - }, - neq: { - type: "custom", - argument_type: { - type: "named", - name: "Integer" - } - }, - gt: { - type: "custom", - argument_type: { - type: "named", - name: "Integer" - } - }, - lt: { - type: "custom", - argument_type: { - type: "named", - name: "Integer" - } - }, - gte: { - type: "custom", - argument_type: { - type: "named", - name: "Integer" - } - }, - lte: { - type: "custom", - argument_type: { - type: "named", - name: "Integer" - } - } - }, - }, - "Number": { - aggregate_functions: { - "count": { - result_type: { - type: "named", - name: BuiltInScalarTypeName.Number, - } - }, - "sum": { - result_type: { - type: "named", - name: BuiltInScalarTypeName.Number, - } - }, - "avg": { - result_type: { - type: "named", - name: BuiltInScalarTypeName.Number, - } - }, - "min": { - result_type: { - type: "named", - name: BuiltInScalarTypeName.Number, - } - }, - "max": { - result_type: { - type: "named", - name: BuiltInScalarTypeName.Number, - } - } - }, - comparison_operators: { - eq: { - type: "equal" - }, - neq: { - type: "custom", - argument_type: { - type: "named", - name: "Number" - } - }, - gt: { - type: "custom", - argument_type: { - type: "named", - name: "Number" - } - }, - lt: { - type: "custom", - argument_type: { - type: "named", - name: "Number" - } - }, - gte: { - type: "custom", - argument_type: { - type: "named", - name: "Number" - } - }, - lte: { - type: "custom", - argument_type: { - type: "named", - name: "Number" - } - } - }, - }, - "Boolean": { - aggregate_functions: { - "bool_and": { - result_type: { - type: "named", - name: BuiltInScalarTypeName.Boolean, - } - }, - "bool_or": { - result_type: { - type: "named", - name: BuiltInScalarTypeName.Boolean, - } - }, - "bool_not": { - result_type: { - type: "named", - name: BuiltInScalarTypeName.Boolean, - } - } - }, - comparison_operators: { - eq: { - type: "equal" - }, - neq: { - type: "custom", - argument_type: { - type: "named", - name: "Boolean" - } - } - }, - }, - "String": { - aggregate_functions: {}, - comparison_operators: { - eq: { - type: "equal" - }, - neq: { - type: "custom", - argument_type: { - type: "named", - name: "String" - } - }, - gt: { - type: "custom", - argument_type: { - type: "named", - name: "String" - } - }, - lt: { - type: "custom", - argument_type: { - type: "named", - name: "String" - } - }, - gte: { - type: "custom", - argument_type: { - type: "named", - name: "String" - } - }, - lte: { - type: "custom", - argument_type: { - type: "named", - name: "String" - } - }, - contains: { - type: "custom", - argument_type: { - type: "named", - name: "String" - } - }, - endswith: { - type: "custom", - argument_type: { - type: "named", - name: "String" - } - }, - regexmatch: { - type: "custom", - argument_type: { - type: "named", - name: "String" - } - }, - startswith: { - type: "custom", - argument_type: { - type: "named", - name: "String" - } - } - }, - } -}; - -export function getJSONScalarTypes(): ScalarTypeDefinitions { - var scalarTypeDefinitions: ScalarTypeDefinitions = {}; - scalarTypeDefinitions["Integer"] = { - type: "named", - name: BuiltInScalarTypeName.Integer, - kind: "scalar" - }; - scalarTypeDefinitions["Number"] = { - type: "named", - name: BuiltInScalarTypeName.Number, - kind: "scalar" - }; - scalarTypeDefinitions["Boolean"] = { - type: "named", - name: BuiltInScalarTypeName.Boolean, - kind: "scalar" - }; - scalarTypeDefinitions["String"] = { - type: "named", - name: BuiltInScalarTypeName.String, - kind: "scalar" - }; - - return scalarTypeDefinitions -} - - - - -export function getNdcSchemaResponse(collectionsSchema: CollectionsSchema): sdk.SchemaResponse { - const collections = Object.entries(collectionsSchema.collections); - - var collectionInfos = collections.map(([collectionName, collectionInfo]) => { - return { - name: collectionName, - description: null, - arguments: {}, - type: getBaseNamedType(collectionInfo.resultType), - uniqueness_constraints: {}, - foreign_keys: {} - } - }) - - - const objectTypes = mapObjectValues(collectionsSchema.objectTypes, objDef => { - return { - fields: Object.fromEntries(Object.values(objDef.properties).map(propDef => { - const objField: sdk.ObjectField = { - type: convertTypeReferenceToSdkType(propDef.type), - description: null - } - return [propDef.propertyName, objField]; - })), - ...(objDef.description ? { description: objDef.description } : {}) - } - }); - - - - return { - functions: [], - procedures: [], - collections: collectionInfos, - object_types: objectTypes, - scalar_types: scalarTypes, - } -} - -function convertTypeReferenceToSdkType(typeRef: TypeDefinition): sdk.Type { - switch (typeRef.type) { - case "array": return { type: "array", element_type: convertTypeReferenceToSdkType(typeRef.elementType) } - case "nullable": return { type: "nullable", underlying_type: convertTypeReferenceToSdkType(typeRef.underlyingType) } - case "named": return { type: "named", name: typeRef.name } - } -} - -export function getBaseNamedType(typeRef: TypeDefinition): string { - switch (typeRef.type) { - case "array": return getBaseNamedType(typeRef.elementType) - case "nullable": return getBaseNamedType(typeRef.underlyingType) - case "named": return typeRef.name - } -} diff --git a/src/sqlGeneration.ts b/src/sqlGeneration.ts deleted file mode 100644 index 8c209b0..0000000 --- a/src/sqlGeneration.ts +++ /dev/null @@ -1,655 +0,0 @@ -import * as sdk from "@hasura/ndc-sdk-typescript"; -import * as cosmos from "@azure/cosmos"; -import { SqlQuerySpec } from "@azure/cosmos"; -import * as schema from "./schema"; - -export type Column = { - name: string, - prefix: string, -} - -export type SelectContainerColumn = { - kind: 'column', - column: Column -} - -export type SelectAggregate = { - kind: 'aggregate', - column: Column, - aggregateFunction: string -} - -export type SelectColumn = SelectContainerColumn | SelectAggregate | SqlQueryContext - -/* - The key represents the alias of the request field and the - value represents the value to be selected from the container. -*/ -export type SelectColumns = { - [alias: string]: SelectColumn -} - -export type QueryVariable = { - [k: string]: unknown -} - -export type QueryVariables = QueryVariable[] | null | undefined - -/* - Type to track the parameters used in the SQL query. - */ -type SqlParameters = { - [column: string]: any[] -} - -export type FromClause = { - source: string, - sourceAlias: string, - in?: string, -} - -export type ContainerExpression = { - kind: 'containerExpression', - containerExpression: string -} - -export type SqlExpression = { - kind: 'sqlExpression', - sqlExpression: SqlQueryContext -} - -export type ArrayJoinTarget = ContainerExpression | SqlExpression - -export type ArrayJoinClause = { - type: 'array', - joinIdentifier: string, - arrayJoinTarget: ArrayJoinTarget, -} - -export type SubqueryJoinClause = { - type: 'subquery', - from: string, - subQuery: SqlQueryContext, - subQueryAs: string, -} - -export type JoinClause = ArrayJoinClause | SubqueryJoinClause; - -type ComparisonScalarDbOperator = { - name: string, - isInfix: boolean -} - -type AggregateScalarDbOperator = { - operator: string, - resultType: string -} - -// Defines how the NDC's scalar operators map to the DB operators -type ScalarDBOperatorMappings = { - comparison: { - [operatorName: string]: ComparisonScalarDbOperator - }, - aggregate?: { - [operatorName: string]: AggregateScalarDbOperator - } | undefined - -}; - -type ScalarOperatorMappings = { - [scalarTypeName: string]: ScalarDBOperatorMappings -} - - -export const scalarComparisonOperatorMappings: ScalarOperatorMappings = { - "Integer": { - "comparison": { - "eq": { - "name": "=", - "isInfix": true - }, - "neq": { - "name": "!=", - "isInfix": true - }, - "gt": { - "name": ">", - "isInfix": true - }, - "lt": { - "name": "<", - "isInfix": true - }, - "gte": { - "name": ">=", - "isInfix": true - }, - "lte": { - "name": "<=", - "isInfix": true - } - }, - "aggregate": { - "count": { - "operator": "count", - "resultType": "Integer" - }, - "sum": { - "operator": "sum", - "resultType": "Integer" - }, - "avg": { - "operator": "sum", - "resultType": "Number" - }, - "min": { - "operator": "sum", - "resultType": "Integer" - }, - "max": { - "operator": "sum", - "resultType": "Integer" - }, - } - }, - "Number": { - "comparison": { - "eq": { - "name": "=", - "isInfix": true - }, - "neq": { - "name": "!=", - "isInfix": true - }, - "gt": { - "name": ">", - "isInfix": true - }, - "lt": { - "name": "<", - "isInfix": true - }, - "gte": { - "name": ">=", - "isInfix": true - }, - "lte": { - "name": "<=", - "isInfix": true - } - }, - "aggregate": { - "count": { - "operator": "count", - "resultType": "Integer" - }, - "sum": { - "operator": "sum", - "resultType": "Number" - }, - "avg": { - "operator": "sum", - "resultType": "Number" - }, - "min": { - "operator": "sum", - "resultType": "Number" - }, - "max": { - "operator": "sum", - "resultType": "Number" - }, - } - }, - "Boolean": { - "comparison": { - "eq": { - "name": "=", - "isInfix": true - }, - "neq": { - "name": "!=", - "isInfix": true - } - }, - "aggregate": { - "bool_and": { - "operator": "bool_and", - "resultType": "Boolean" - }, - "bool_or": { - "operator": "bool_or", - "resultType": "Boolean" - }, - "bool_not": { - "operator": "bool_or", - "resultType": "Boolean" - }, - } - - }, - "String": { - "comparison": { - "eq": { - "name": "=", - "isInfix": true - }, - "neq": { - "name": "!=", - "isInfix": true - }, - "gt": { - "name": ">", - "isInfix": true - }, - "lt": { - "name": "<", - "isInfix": true - }, - "gte": { - "name": ">=", - "isInfix": true - }, - "lte": { - "name": "<=", - "isInfix": true - }, - "contains": { - "name": "CONTAINS", - "isInfix": false, - }, - "endswith": { - "name": "ENDSWITH", - "isInfix": false, - }, - "regexmatch": { - "name": "REGEXMATCH", - "isInfix": false, - }, - "startswith": { - "name": "STARTSWITH", - "isInfix": false - } - } - - }, -}; - -export function getDbComparisonOperator(scalarTypeName: string, operator: string): ComparisonScalarDbOperator { - const scalarOperators = scalarComparisonOperatorMappings[scalarTypeName]; - - if (scalarOperators === undefined && scalarOperators === null) { - throw new sdk.BadRequest(`Couldn't find scalar type: ${scalarTypeName} in the schema`) - } else { - const scalarDbOperator = scalarOperators.comparison[operator]; - - if (scalarDbOperator) { - return scalarDbOperator - } else { - throw new sdk.BadRequest(`Comparison Operator ${operator} is not supported on type ${scalarTypeName}`) - } - } - - -} - - -export type ComparisonTarget = - | { - type: "column"; - /** - * The name of the column - */ - name: string; - } - | { - type: "root_collection_column"; - /** - * The name of the column - */ - name: string; - }; - -export type ComparisonValue = - | { - type: "column"; - column: string; - } - | { - type: "scalar"; - value: unknown; - } - | { - type: "variable"; - name: string; - }; - -export type Expression = - | { - type: "and"; - expressions: Expression[]; - } - | { - type: "or"; - expressions: Expression[]; - } - | { - type: "not"; - expression: Expression; - } - | { - type: "unary_comparison_operator"; - column: string; - operator: "is_null"; - } - | { - type: "binary_comparison_operator"; - column: string; - value: ComparisonValue; - dbOperator: ComparisonScalarDbOperator; - }; - - - - -export type SqlQueryContext = { - kind: 'sqlQueryContext', - select: SelectColumns, - /* Set to `true` to prevent the wrapping of the results into another JSON object. */ - selectAsValue: boolean, - from?: FromClause | null, - join?: JoinClause[] | null, - predicate?: Expression | null, - offset?: number | null, - limit?: number | null, - orderBy?: sdk.OrderBy | null, - isAggregateQuery: boolean, - selectAsArray?: boolean | undefined -} - -type VariablesMappings = { - /* - The variableTarget will be the name of the column - which gets the value of the variable - */ - [variableTarget: string]: string -} - -function formatJoinClause(joinClause: JoinClause): string { - if (joinClause.type === "array") { - let joinTarget = - joinClause.arrayJoinTarget.kind === 'containerExpression' - ? joinClause.arrayJoinTarget.containerExpression - : constructSqlQuery(joinClause.arrayJoinTarget.sqlExpression, joinClause.joinIdentifier, null); - - return `${joinClause.joinIdentifier} in (${joinTarget})` - } else { - return `(${constructSqlQuery(joinClause.subQuery, joinClause.from, null).query}) ${joinClause.subQueryAs}`; - } - -} - -function formatFromClause(fromClause: FromClause): string { - if (fromClause.in !== undefined) { - return `${fromClause.in} IN ${fromClause.source}` - } else { - return `${fromClause.source} ${fromClause.sourceAlias}` - } -} - -/** Constructs a SQL query from the given `sqlQueryContext` - * @param sqlQueryCtx - `SqlQueryContext` which contains the data required to generate the SQL query. - * @param source - `source` to run the query on. Note that, the source can be a container or a nested field of a document of a container. - * @param queryVariables - values of the variables provided with the request. - - */ -function constructSqlQuery(sqlQueryCtx: SqlQueryContext, source: string, queryVariables: QueryVariables): cosmos.SqlQuerySpec { - let selectColumns = formatSelectColumns(sqlQueryCtx.select); - - let fromClause = - sqlQueryCtx.from === null || sqlQueryCtx.from === undefined - ? null : - formatFromClause(sqlQueryCtx.from); - - let whereClause = null; - let predicateParameters: SqlParameters = {}; - let utilisedVariables: VariablesMappings = {}; // This will be used to add the join mappings to the where expression. - - let parameters: cosmos.SqlParameter[] = []; - - if (sqlQueryCtx.predicate != null && sqlQueryCtx.predicate != undefined) { - - const whereExp = visitExpression(predicateParameters, utilisedVariables, sqlQueryCtx.predicate, source); - - whereClause = `WHERE ${whereExp}` - - parameters = serializeSqlParameters(predicateParameters); - - if (Object.keys(utilisedVariables).length > 0) { - if (queryVariables === null || queryVariables === undefined) { - throw new sdk.BadRequest(`The variables (${JSON.stringify(Object.values(utilisedVariables))}) were referenced in the variable, but their values were not provided`) - } else { - parameters.push({ - name: '@vars', - value: queryVariables as cosmos.JSONValue - }); - } - - } - } - - let joinClause = null; - - if (Object.keys(utilisedVariables).length > 0) { - let variablesJoinTarget: ArrayJoinTarget = { - kind: 'containerExpression', - containerExpression: 'SELECT VALUE @vars' - }; - let joinExp: JoinClause = { - type: 'array', - joinIdentifier: "vars", - arrayJoinTarget: variablesJoinTarget, - }; - joinClause = `JOIN ${formatJoinClause(joinExp)}` - } - - let orderByClause = null; - - if (sqlQueryCtx.orderBy != null && sqlQueryCtx.orderBy != null && sqlQueryCtx.orderBy.elements.length > 0) { - orderByClause = visitOrderByElements(sqlQueryCtx.orderBy.elements, source); - } - - let offsetClause = null; - - if (sqlQueryCtx.offset != undefined && sqlQueryCtx.offset != null) { - offsetClause = `${sqlQueryCtx.offset}`; - } - - let limitClause = null; - - if (sqlQueryCtx.limit != undefined && sqlQueryCtx.limit != null) { - limitClause = `${sqlQueryCtx.limit}` - - } - - let query = - `SELECT ${sqlQueryCtx.selectAsValue ? 'VALUE' : ''} ${selectColumns} - ${fromClause ? 'FROM ' + fromClause : ''} - ${joinClause ?? ''} - ${whereClause ?? ''} - ${orderByClause ? 'ORDER BY ' + orderByClause : ''} - ${offsetClause ? 'OFFSET ' + offsetClause : ''} - ${limitClause ? 'LIMIT ' + limitClause : ''}`; - - - return { - query, - parameters - } -} - -export function generateSqlQuerySpec(sqlGenCtx: SqlQueryContext, containerName: string, queryVariables: QueryVariables, schema: schema.CollectionsSchema): SqlQuerySpec { - - return constructSqlQuery(sqlGenCtx, `root_${containerName}`, queryVariables); - -} - -export function formatColumn(column: Column) { - return `${column.prefix}.${column.name}` -} - - -function formatSelectColumns(fieldsToSelect: SelectColumns): string { - if (Object.keys(fieldsToSelect).length === 0) { - return "VALUE {}" - } - return Object.entries(fieldsToSelect).map(([alias, selectColumn]) => { - switch (selectColumn.kind) { - case 'column': - return `${formatColumn(selectColumn.column)} ?? null as ${alias}` - case 'sqlQueryContext': - let query = constructSqlQuery(selectColumn, alias, null).query.trim(); - if (selectColumn.selectAsArray) { - return `(ARRAY(${query})) as ${alias}` - } else { - return `(${query}) as ${alias}` - } - case 'aggregate': - return `${selectColumn.aggregateFunction} (${formatColumn(selectColumn.column)}) as ${alias} ` - } - }).join(","); - -} - -/* - Traverses over the order by elements and generates the ORDER BY clause. - NOTE that this function expects the `values` parameter to be a non-empty list. - */ -function visitOrderByElements(values: sdk.OrderByElement[], containerAlias: string): string { - if (values.length === 0) { - throw new sdk.InternalServerError("visit_order_by_elements called with an empty list") - } - return values.map(element => visitOrderByElement(element, containerAlias)).join(", "); - -} - -function visitOrderByElement(value: sdk.OrderByElement, containerAlias: string): string { - const direction = value.order_direction === 'asc' ? 'ASC' : 'DESC'; - - switch (value.target.type) { - case 'column': - if (value.target.path.length > 0) { - throw new sdk.NotSupported("Relationships are not supported in order_by.") - } else { - return `${containerAlias}.${value.target.name} ${direction} ` - } - - case 'single_column_aggregate': - throw new sdk.NotSupported("Order by aggregate is not supported") - - case 'star_count_aggregate': - throw new sdk.NotSupported("Order by aggregate is not supported") - } -} - -/* - Wraps the expression in parantheses to avoid generating SQL with wrong operator precedence. - */ -function visitExpressionWithParentheses(parameters: SqlParameters, variables: VariablesMappings, expression: Expression, containerAlias: string): string { - return `(${visitExpression(parameters, variables, expression, containerAlias)})` -} - -function visitExpression(parameters: SqlParameters, variables: VariablesMappings, expression: Expression, containerAlias: string): string { - switch (expression.type) { - case "and": - if (expression.expressions.length > 0) { - return expression.expressions.map(expr => visitExpressionWithParentheses(parameters, variables, expr, containerAlias)).join(" AND ") - } else { - return "true" - }; - - case "or": - if (expression.expressions.length > 0) { - return expression.expressions.map(expr => visitExpressionWithParentheses(parameters, variables, expr, containerAlias)).join(" OR ") - } else { - return "false" - }; - - case "not": - return `NOT ${visitExpressionWithParentheses(parameters, variables, expression.expression, containerAlias)} ` - - case "unary_comparison_operator": - switch (expression.operator) { - case "is_null": - return `IS_NULL(${expression.column})` - } - - case "binary_comparison_operator": - const comparisonValue = visitComparisonValue(parameters, variables, expression.value, expression.column, containerAlias); - - if (expression.dbOperator.isInfix) { - return `${containerAlias}.${expression.column} ${expression.dbOperator.name} ${comparisonValue}` - } else { - return `${expression.dbOperator.name}(${containerAlias}.${expression.column}, ${comparisonValue}) ` - } - - } -} - -export function visitComparisonTarget(target: sdk.ComparisonTarget): string { - switch (target.type) { - case 'column': - if (target.path.length > 0) { - throw new sdk.NotSupported("Relationship fields are not supported in predicates."); - } - return target.name; - case 'root_collection_column': - throw new sdk.NotSupported("Root collection column comparison is not supported"); - } -} - -function visitComparisonValue(parameters: SqlParameters, variables: VariablesMappings, target: ComparisonValue, comparisonTarget: string, containerAlias: string): string { - switch (target.type) { - case 'scalar': - const comparisonTargetName = comparisonTarget.replace(".", "_"); - const comparisonTargetParameterValues = parameters[comparisonTargetName]; - if (comparisonTargetParameterValues != null) { - const index = comparisonTargetParameterValues.findIndex((element) => element === target.value); - if (index !== -1) { - return `@${comparisonTargetName}_${index} ` - } else { - let newIndex = parameters[comparisonTargetName].push(target.value); - return `@${comparisonTargetName}_${newIndex} ` - } - } else { - parameters[comparisonTargetName] = [target.value]; - return `@${comparisonTargetName}_0` - } - - case 'column': - return `${containerAlias}.${target.column}` - - case 'variable': - variables[comparisonTarget] = `vars["${target.name}"]` - return `vars["${target.name}"]` - - } -} - -function serializeSqlParameters(parameters: SqlParameters): cosmos.SqlParameter[] { - let sqlParameters: cosmos.SqlParameter[] = []; - - for (const comparisonTarget in parameters) { - const comparisonTargetValues = parameters[comparisonTarget]; - - for (let i = 0; i < comparisonTargetValues.length; i++) { - sqlParameters.push({ - name: `@${comparisonTarget}_${i}`, - value: comparisonTargetValues[i] - }) - } - } - - return sqlParameters -} diff --git a/tests/introspect_schema.test.ts b/tests/introspect_schema.test.ts index 6b41337..ad0a07a 100644 --- a/tests/introspect_schema.test.ts +++ b/tests/introspect_schema.test.ts @@ -1,17 +1,23 @@ import { expect } from "chai"; -import { getObjectTypeDefinitionsFromJSONSchema, inferJSONSchemaFromContainerRows } from "../src/cli/config" +import { + getObjectTypeDefinitionsFromJSONSchema, + inferJSONSchemaFromContainerRows, +} from "../src/cli/config"; -describe("Infer schema of JSON value", function() { - it("infers the schema of a simple object", async function() { - let simpleObject = `{ +describe("Infer schema of JSON value", function () { + it("infers the schema of a simple object", async function () { + let simpleObject = `{ a: "b" }`; - let inferredJSONSchema = await inferJSONSchemaFromContainerRows([simpleObject], "simple"); - let objectTypeDefns = await getObjectTypeDefinitionsFromJSONSchema(inferredJSONSchema); + let inferredJSONSchema = await inferJSONSchemaFromContainerRows( + [simpleObject], + "simple", + ); + let objectTypeDefns = + await getObjectTypeDefinitionsFromJSONSchema(inferredJSONSchema); - // TODO: Fix this test + // TODO: Fix this test - expect("1", "1") - - }) -}) + expect("1", "1"); + }); +}); diff --git a/tests/introspect_schema.ts b/tests/introspect_schema.ts deleted file mode 100644 index ac5e48e..0000000 --- a/tests/introspect_schema.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { expect } from "chai"; -import { getObjectTypeDefinitionsFromJSONSchema, inferJSONSchemaFromContainerRows } from "../src/introspectContainerSchema" - -describe("Infer schema of JSON value", function() { - it("infers the schema of a simple object", async function() { - let simpleObject = `{ - a: "b" - }`; - let inferredJSONSchema = await inferJSONSchemaFromContainerRows([simpleObject], "simple"); - let objectTypeDefns = getObjectTypeDefinitionsFromJSONSchema(inferredJSONSchema); - - expect("1", "1") - - }) -}) diff --git a/tests/nested_filtering.ts b/tests/nested_filtering.ts new file mode 100644 index 0000000..84f347b --- /dev/null +++ b/tests/nested_filtering.ts @@ -0,0 +1,199 @@ +import * as sql from "../src/connector/sql/sqlGeneration"; +import { expect } from "chai"; + +let lteComparisonOperator: sql.ComparisonScalarDbOperator = { + name: "<=", + isInfix: true, + isUnary: false, +}; + +/* +{ + "nested_array_object_object_array": [ + { + "b": { + "c": [ + { + "d": 1 + } + ] + } + }, + { + "b": { + "c": [ + { + "d": 2 + } + ] + } + } + ] + } + + */ +let nestedArrayObjectObjectArray: sql.Column = { + name: "nested_array_object_object_array", + prefix: "users", + nestedField: { + kind: "array", + nestedField: { + kind: "object", + field: "b", + nestedField: { + kind: "object", + field: "c", + nestedField: { + kind: "array", + nestedField: { + kind: "scalar", + type: "Integer", + field: "d", + }, + }, + }, + }, + }, +}; + +/* + { + "nested_object_object_object": { + "b": { + "c": { + "d": 2 + } + } + } + } + + */ +let nestedObjectObjectObject: sql.Column = { + name: "nested_object_object_object", + prefix: "users", + nestedField: { + kind: "object", + field: "b", + nestedField: { + kind: "object", + field: "c", + nestedField: { + kind: "scalar", + type: "Integer", + field: "d", + }, + }, + }, +}; + +// Generate test cases for translateWhereExpression + +describe("Nested filtering", function () { + it("deeply nested array object object array predicate", async function () { + let variableMap = {}; + let parameterMap = {}; + let query = sql.translateWhereExpression( + { + kind: "simpleWhereExpression", + column: nestedArrayObjectObjectArray, + operator: lteComparisonOperator, + value: { + type: "scalar", + value: 2, + }, + }, + parameterMap, + variableMap, + ); + expect(query).to.equal( + `EXISTS( + SELECT 1 + FROM array_element_1 IN users.nested_array_object_object_array + WHERE EXISTS( + SELECT 1 + FROM array_element_2 IN array_element_1.b.c + WHERE array_element_2.d <= @d_0))`, + ); + + expect(parameterMap).to.deep.equal({ d: [2] }); + }); + + it("deeply nested object filtering predicate", async function () { + let variableMap = {}; + let parameterMap = {}; + let query = sql.translateWhereExpression( + { + kind: "simpleWhereExpression", + column: nestedObjectObjectObject, + operator: lteComparisonOperator, + value: { + type: "scalar", + value: 2, + }, + }, + parameterMap, + variableMap, + ); + + expect(query).to.equal(`users.nested_object_object_object.b.c.d <= @d_0`); + + expect(parameterMap).to.deep.equal({ d: [2] }); + }); + + it("Compound predicates combined using AND", async function () { + let variableMap = {}; + let parameterMap = {}; + let query = sql.translateWhereExpression( + { + kind: "and", + expressions: [ + { + kind: "simpleWhereExpression", + column: nestedObjectObjectObject, + operator: lteComparisonOperator, + value: { + type: "scalar", + value: 2, + }, + }, + { + kind: "simpleWhereExpression", + column: nestedObjectObjectObject, + operator: lteComparisonOperator, + value: { + type: "scalar", + value: 3, + }, + }, + { + kind: "simpleWhereExpression", + column: { + name: "username", + prefix: "users", + }, + operator: { + name: "=", + isInfix: true, + isUnary: false, + }, + value: { + type: "scalar", + value: "Kacie-Leffler", + }, + }, + ], + }, + parameterMap, + variableMap, + ); + + expect(query).to.eq( + `(users.nested_object_object_object.b.c.d <= @d_0) AND (users.nested_object_object_object.b.c.d <= @d_1) AND (users.username = @username_0)`, + ); + + expect(parameterMap).to.deep.equal({ + d: [2, 3], + username: ["Kacie-Leffler"], + }); + }); +}); diff --git a/tests/sqlGeneration.test.ts b/tests/sqlGeneration.test.ts new file mode 100644 index 0000000..b89c67e --- /dev/null +++ b/tests/sqlGeneration.test.ts @@ -0,0 +1,234 @@ +// Generate test cases for generateSqlQuerySpec function + +import { + constructSqlQuery, + SqlQueryContext, +} from "../src/connector/sql/sqlGeneration"; +import { SqlQuerySpec } from "@azure/cosmos"; + +import { expect } from "chai"; + +// write a function that removes all whitespace from a string +function removeWhitespace(s: string): string { + return s.replace(/\s/g, ""); +} + +function normalizeSQL(sql: string): string { + return sql + .replace(/\s+/g, " ") // Replace multiple whitespace characters with a single space + .replace(/\s*([(),])\s*/g, "$1") // Remove spaces around parentheses and commas + .trim() // Remove leading and trailing whitespace + .toLowerCase(); // Convert to lowercase for case-insensitive comparison +} + +function assertSQLEqual(actual: string, expected: string) { + const normalizedActual = normalizeSQL(actual); + const normalizedExpected = normalizeSQL(expected); + + expect(normalizedActual).to.equal(normalizedExpected); +} + +describe("constructSqlQuery", () => { + it("should construct a basic SQL query with select and from clauses", () => { + const sqlQueryCtx: SqlQueryContext = { + kind: "sqlQueryContext", + select: { + id: { kind: "column", column: { name: "id", prefix: "u" } }, + name: { kind: "column", column: { name: "name", prefix: "u" } }, + }, + from: { source: "users", sourceAlias: "u" }, + selectAsValue: false, + isAggregateQuery: false, + }; + + const result: SqlQuerySpec = constructSqlQuery(sqlQueryCtx, "u", null); + + assertSQLEqual( + result.query, + `SELECT u.id ?? null as id,u.name ?? null as name FROM users u`, + ); + + expect(result.parameters?.length).to.equals(0); + }); + + it("should handle a query with a where clause and parameters", () => { + const sqlQueryCtx: SqlQueryContext = { + kind: "sqlQueryContext", + select: { + id: { kind: "column", column: { name: "id", prefix: "u" } }, + }, + from: { source: "users", sourceAlias: "u" }, + predicate: { + kind: "and", + expressions: [ + { + kind: "simpleWhereExpression", + column: { name: "age", prefix: "u" }, + operator: { name: ">", isInfix: true, isUnary: false }, + value: { type: "scalar", value: 19 }, + }, + { + kind: "simpleWhereExpression", + column: { name: "age", prefix: "u" }, + operator: { name: ">", isInfix: true, isUnary: false }, + value: { + type: "scalar", + value: 18, + }, + }, + ], + }, + selectAsValue: false, + isAggregateQuery: false, + }; + + const result: SqlQuerySpec = constructSqlQuery(sqlQueryCtx, "u", null); + + assertSQLEqual( + result.query, + `SELECT u.id ?? null as id + FROM users u + WHERE (u.age > @age_0) AND (u.age > @age_1)`, + ); + + expect(result.parameters).to.deep.equal([ + { name: "@age_0", value: 19 }, + { name: "@age_1", value: 18 }, + ]); + }); + + it("should construct a query with orderBy, offset, and limit clauses", () => { + const sqlQueryCtx: SqlQueryContext = { + kind: "sqlQueryContext", + select: { + name: { kind: "column", column: { name: "name", prefix: "u" } }, + }, + from: { source: "users", sourceAlias: "u" }, + orderBy: { + elements: [ + { + order_direction: "asc", + target: { + type: "column", + name: "name", + path: [], + }, + }, + ], + }, + offset: 10, + limit: 5, + selectAsValue: false, + isAggregateQuery: false, + }; + + const result: SqlQuerySpec = constructSqlQuery(sqlQueryCtx, "u", null); + + assertSQLEqual( + result.query, + `SELECT u.name ?? null as name + FROM users u + ORDER BY u.name ASC + OFFSET 10 + LIMIT 5`, + ); + }); + + it("should handle a query with an aggregate function", () => { + const sqlQueryCtx: SqlQueryContext = { + kind: "sqlQueryContext", + select: { + total: { + kind: "aggregate", + column: { name: "amount", prefix: "o" }, + aggregateFunction: "SUM", + }, + }, + from: { source: "orders", sourceAlias: "o" }, + selectAsValue: false, + isAggregateQuery: true, + }; + + const result: SqlQuerySpec = constructSqlQuery(sqlQueryCtx, "orders", null); + + assertSQLEqual(result.query, `SELECT SUM(o.amount) as total FROM orders o`); + }); + + it("should handle a query with selectAsValue set to true", () => { + const sqlQueryCtx: SqlQueryContext = { + kind: "sqlQueryContext", + select: { + id: { kind: "column", column: { name: "id", prefix: "u" } }, + }, + from: { source: "users", sourceAlias: "u" }, + selectAsValue: true, + isAggregateQuery: false, + }; + + const result: SqlQuerySpec = constructSqlQuery(sqlQueryCtx, "u", null); + + assertSQLEqual( + result.query, + `SELECT VALUE u.id ?? null as id FROM users u`, + ); + }); + + it("should handle a query with a predicate on a column with a nested field", () => { + const sqlQueryCtx: SqlQueryContext = { + kind: "sqlQueryContext", + select: { + id: { kind: "column", column: { name: "id", prefix: "u" } }, + }, + from: { source: "users", sourceAlias: "u" }, + predicate: { + kind: "simpleWhereExpression", + column: { + name: "nested_array_object_object_array", + prefix: "u", + nestedField: { + kind: "array", + nestedField: { + kind: "object", + field: "b", + nestedField: { + kind: "object", + field: "c", + nestedField: { + kind: "array", + nestedField: { + kind: "scalar", + type: "Integer", + field: "d", + }, + }, + }, + }, + }, + }, + operator: { name: "=", isInfix: true, isUnary: false }, + value: { type: "scalar", value: "Seattle" }, + }, + selectAsValue: false, + isAggregateQuery: false, + }; + + const result: SqlQuerySpec = constructSqlQuery(sqlQueryCtx, "u", null); + + assertSQLEqual( + result.query, + `SELECT u.id ?? null as id + FROM users u + WHERE EXISTS( + SELECT 1 + FROM array_element_1 IN u.nested_array_object_object_array + WHERE EXISTS( + SELECT 1 + FROM array_element_2 IN array_element_1.b.c + WHERE array_element_2.d = @d_0))`, + ); + + expect(result.parameters).to.deep.equal([ + { name: "@d_0", value: "Seattle" }, + ]); + }); +});