diff --git a/tutorials/hana-clients-cf/hana-clients-cf.md b/tutorials/hana-clients-cf/hana-clients-cf.md index 8152f77d6..88b520397 100644 --- a/tutorials/hana-clients-cf/hana-clients-cf.md +++ b/tutorials/hana-clients-cf/hana-clients-cf.md @@ -4,7 +4,7 @@ author_name: Dan van Leeuwen author_profile: https://github.com/danielva auto_validation: true time: 15 -tags: [ tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana, programming-tool>node-js, software-product>sap-btp--cloud-foundry-runtime-and-environment, software-product>sap-business-technology-platform, software-product>sap-connectivity-service] +tags: [tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana, programming-tool>node-js, software-product>sap-btp--cloud-foundry-runtime-and-environment, software-product>sap-business-technology-platform, software-product>sap-connectivity-service] primary_tag: software-product>sap-hana-cloud --- @@ -36,9 +36,9 @@ The command line interface (CLI) for Cloud Foundry is named `cf` while the CLI u 1. Check to see if you have the CF CLI installed and verify the version. - ```Shell - cf -v - ``` + ```Shell + cf -v + ``` ![cf cli version](new-cf-version.png) @@ -46,9 +46,9 @@ The command line interface (CLI) for Cloud Foundry is named `cf` while the CLI u Check to see if you have the XS CLI installed and verify its version. - ```Shell - xs -v - ``` + ```Shell + xs -v + ``` ![xs cli version](xsShowVersion.png) @@ -56,21 +56,21 @@ The command line interface (CLI) for Cloud Foundry is named `cf` while the CLI u 2. Access help by running the following: - ```Shell - cf help - cf help login - ``` + ```Shell + cf help + cf help login + ``` - ```Shell - xs help - xs help login - ``` + ```Shell + xs help + xs help login + ``` 3. Log in to the Cloud Foundry or XS advanced. - ```Shell - cf login - ``` + ```Shell + cf login + ``` ![cf login](cfLogin.png) @@ -82,15 +82,15 @@ The command line interface (CLI) for Cloud Foundry is named `cf` while the CLI u The API URL can be set with the below command. - ```Shell - cf api - ``` + ```Shell + cf api + ``` **XS advanced** - ```Shell - xs login - ``` + ```Shell + xs login + ``` ![xs login](xsLogin.png) @@ -100,23 +100,23 @@ The command line interface (CLI) for Cloud Foundry is named `cf` while the CLI u 4. Additional examples are shown below to view the target information, running services, and deployed apps. - ```Shell - cf target - cf services - cf apps - cf buildpacks - ``` + ```Shell + cf target + cf services + cf apps + cf buildpacks + ``` - **XS advanced** + **XS advanced** - ```Shell - xs target - xs services - xs apps - xs buildpacks - ``` + ```Shell + xs target + xs services + xs apps + xs buildpacks + ``` - ![services](cliExample.png) + ![Services](cliExample.png) Additional details can be found at [Getting Started with the cf CLI](https://docs.cloudfoundry.org/cf-cli/getting-started.html) and [Get Started with the XS CLI Client](https://help.sap.com/docs/SAP_HANA_PLATFORM/4505d0bdaf4948449b7f7379d24d0f0d/c00ed3f74c12479e9f3a8cdeb6e1519a.html). @@ -124,91 +124,107 @@ The command line interface (CLI) for Cloud Foundry is named `cf` while the CLI u 1. Create a folder named `nodeCF\nodeQueryCF` and enter the newly created directory. - ```Shell (Microsoft Windows) - mkdir %HOMEPATH%\HANAClientsTutorial\nodeCF\nodeQueryCF - cd %HOMEPATH%\HANAClientsTutorial\nodeCF\nodeQueryCF - ``` + [OPTION BEGIN [Windows]] + + ```Shell + mkdir %HOMEPATH%\HANAClientsTutorial\nodeCF\nodeQueryCF + cd %HOMEPATH%\HANAClientsTutorial\nodeCF\nodeQueryCF + ``` + + [OPTION END] + + [OPTION BEGIN [Linux and Mac]] - ```Shell (Linux or Mac) - mkdir -p $HOME/HANAClientsTutorial/nodeCF/nodeQueryCF - cd $HOME/HANAClientsTutorial/nodeCF/nodeQueryCF - ``` + ```Shell + mkdir -p $HOME/HANAClientsTutorial/nodeCF/nodeQueryCF + cd $HOME/HANAClientsTutorial/nodeCF/nodeQueryCF + ``` + + [OPTION END] 2. Initialize the project, install [express](https://www.npmjs.com/package/express), and `@sap/hana-client` from NPM. - ```Shell - npm init -y - npm install express - npm install @sap/hana-client - ``` + ```Shell + npm init -y + npm install express + npm install @sap/hana-client + ``` 3. Open a file named `server.js` in an editor. - ```Shell (Microsoft Windows) - notepad server.js - ``` + [OPTION BEGIN [Windows]] + + ```Shell + notepad server.js + ``` + + [OPTION END] - ```Shell (Linux or Mac) - pico server.js - ``` + [OPTION BEGIN [Linux and Mac]] + + ```Shell + pico server.js + ``` + + [OPTION END] 4. Add the code below to `server.js`. Be sure to update the `serverNode` value (SQL Endpoint from your instance) and user credentials if necessary. - ```JavaScript - var express = require('express'); - var hana = require('@sap/hana-client'); - var app = express(); - - app.get('/', function (req, res) { - res.send('Hello World'); - }) - - app.get('/Customers', function (req, res) { - var connOptions = { - serverNode: 'XXXXXX.hana.trial-XXXXX.hanacloud.ondemand.com:443', - //serverNode: 'linux-bj72:39015', - UID: 'USER1', - PWD: 'Password1' - //traceFile: 'stdout', - //traceOptions: 'sql=warning' - }; - - var connection = hana.createConnection(); - connection.connect(connOptions, function(err) { - if (err) { - return console.error(err); - } - var sql = 'select * from HOTELS.CUSTOMER;'; - var rows = connection.exec(sql, function(err, rows) { - if (err) { - return console.error(err); - } - console.log(rows); - res.send(rows); - connection.disconnect(function(err) { - if (err) { - return console.error(err); - } - }); - }); - }); - }) - - const port = process.env.PORT || 3000; - var server = app.listen(port, function () { - var host = server.address().address - var port = server.address().port - console.log("Example app listening at http://%s:%s", host, port) - }) - ``` + ```JavaScript + var express = require('express'); + var hana = require('@sap/hana-client'); + var app = express(); + + app.get('/', function (req, res) { + res.send('Hello World'); + }) + + app.get('/Customers', function (req, res) { + var connOptions = { + serverNode: 'XXXXXX.hana.trial-XXXXX.hanacloud.ondemand.com:443', + //serverNode: 'linux-bj72:39015', + UID: 'USER1', + PWD: 'Password1' + //traceFile: 'stdout', + //traceOptions: 'sql=warning' + }; + + var connection = hana.createConnection(); + connection.connect(connOptions, function(err) { + if (err) { + return console.error(err); + } + var sql = 'select * from HOTELS.CUSTOMER;'; + var rows = connection.exec(sql, function(err, rows) { + if (err) { + return console.error(err); + } + console.log(rows); + res.send(rows); + connection.disconnect(function(err) { + if (err) { + return console.error(err); + } + }); + }); + }); + }) + + const port = process.env.PORT || 3000; + var server = app.listen(port, function () { + var host = server.address().address + var port = server.address().port + console.log("Example app listening at http://%s:%s", host, port) + }) + ``` Update the values for host and port. 5. Run and test the app locally. - ```Shell - node server.js - ``` + ```Shell + node server.js + ``` Open a browser and enter a URL similar to http://localhost:3000/Customers. @@ -218,28 +234,36 @@ The command line interface (CLI) for Cloud Foundry is named `cf` while the CLI u 1. Create a deployment descriptor. - ```Shell (Microsoft Windows) - cd .. - notepad manifest.yml - ``` + [OPTION BEGIN [Windows]] + + ```Shell + cd .. + notepad manifest.yml + ``` + + [OPTION END] - ```Shell (Linux or Mac) - cd .. - pico manifest.yml - ``` + [OPTION BEGIN [Linux and Mac]] + + ```Shell + cd .. + pico manifest.yml + ``` + + [OPTION END] Add the code below to `manifest.yml`. - ```yml - --- - applications: - - name: nodeQueryCF - random-route: true - type: nodejs - path: nodeQueryCF - command: node server.js - memory: 128M - ``` + ```yaml + --- + applications: + - name: nodeQueryCF + random-route: true + type: nodejs + path: nodeQueryCF + command: node server.js + memory: 128M + ``` For additional details, consult [App Manifest Attribute Reference](https://docs.cloudfoundry.org/devguide/deploy-apps/manifest-attributes.html). @@ -255,29 +279,29 @@ The command line interface (CLI) for Cloud Foundry is named `cf` while the CLI u After verifying that you have the necessary entitlements, run the following: - ```Shell - cf push - ``` + ```Shell + cf push + ``` ![Push result](cfPush.png) Notice above the URL to open the app was generated as the `manifest.yml` contained the random-route setting. - ```Shell - xs push - ``` + ```Shell + xs push + ``` ![Push result](xsPush.png) Alternatively, the URL of the app can be found by running the following command: - ```Shell - cf app nodeQueryCF - ``` + ```Shell + cf app nodeQueryCF + ``` - ```Shell - xs app nodeQueryCF - ``` + ```Shell + xs app nodeQueryCF + ``` 3. Test the app. @@ -297,56 +321,56 @@ For additional details see: 1. The available buildpacks can be found using the command below. - ```Shell - cf buildpacks - ``` + ```Shell + cf buildpacks + ``` - If you use another buildpack such as .NET and encounter the error "Cannot find a matching libadonetHDB.so", this can be corrected by adding the below entry to the .csproj file. + If you use another buildpack such as .NET and encounter the error "Cannot find a matching libadonetHDB.so", this can be corrected by adding the below entry to the .csproj file. - ```Shell - - - PreserveNewest - - - ``` + ```Shell + + + PreserveNewest + + + ``` 2. The app can be stopped and started with the below commands: - ```Shell - cf stop nodeQueryCF - cf start nodeQueryCF - ``` + ```Shell + cf stop nodeQueryCF + cf start nodeQueryCF + ``` 3. The applications lifecycle events can be seen with the below command: - ```Shell - cf events nodeQueryCF - ``` + ```Shell + cf events nodeQueryCF + ``` ![Events](events.png) 4. The logs of the application can be seen with the below command: - ```Shell - cf logs nodeQueryCF --recent - ``` + ```Shell + cf logs nodeQueryCF --recent + ``` The following command will show the tail of the log. - ```Shell - cf logs nodeQueryCF - ``` + ```Shell + cf logs nodeQueryCF + ``` 5. As of version 2.7, the SAP HANA client interfaces can output trace information to `stdout` or `stderr`. - ```Shell - cf set-env nodeQueryCF HDB_SQLDBC_TRACEFILE stdout - cf set-env nodeQueryCF HDB_SQLDBC_TRACEOPTS SQL=WARN - cf restage nodeQueryCF - cf env nodeQueryCF - cf logs nodeQueryCF - ``` + ```Shell + cf set-env nodeQueryCF HDB_SQLDBC_TRACEFILE stdout + cf set-env nodeQueryCF HDB_SQLDBC_TRACEOPTS SQL=WARN + cf restage nodeQueryCF + cf env nodeQueryCF + cf logs nodeQueryCF + ``` > Alternatively, the trace settings can be specified in the application code. @@ -396,127 +420,151 @@ The [Cloud Connector](https://help.sap.com/docs/connectivity/sap-btp-connectivit 3. Add the service name to the project's manifest.yml. - ```Shell (Microsoft Windows) - cd %HOMEPATH%\HANAClientsTutorial\nodeCF - notepad manifest.yml - ``` + [OPTION BEGIN [Windows]] + + ```Shell + cd %HOMEPATH%\HANAClientsTutorial\nodeCF + notepad manifest.yml + ``` + + [OPTION END] - ```Shell (Linux or Mac) - cd $HOME/HANAClientsTutorial/nodeCF - pico manifest.yml - ``` + [OPTION BEGIN [Linux and Mac]] - ```yml - services: - - MyConnectivityService - ``` + ```Shell + cd $HOME/HANAClientsTutorial/nodeCF + pico manifest.yml + ``` + + [OPTION END] + + ```yaml + services: + - MyConnectivityService + ``` 4. Make a backup of the server.js file and add the node module `axios` which is promise based HTTP client and is used to fetch a JWT token. For further details see [SAP Cloud Platform: How to call – on-Premise System – from Node.js app – via Cloud Connector](https://blogs.sap.com/2020/08/07/sap-cloud-platform-how-to-call-onprem-system-from-node.js-app-via-cloud-connector). - ```Shell (Microsoft Windows) - cd nodeQueryCF - copy server.js server.js.bak - npm install axios - ``` + [OPTION BEGIN [Windows]] + + ```Shell + cd nodeQueryCF + copy server.js server.js.bak + npm install axios + ``` - ```Shell (Linux or Mac) - cd nodeQueryCF - cp server.js server.js.bak - npm install axios - ``` + [OPTION END] + + [OPTION BEGIN [Linux and Mac]] + + ```Shell + cd nodeQueryCF + cp server.js server.js.bak + npm install axios + ``` + + [OPTION END] 5. Open the file named `server.js` in an editor and replace the contents where necessary. - ```Shell (Microsoft Windows) - notepad server.js - ``` - - ```Shell (Linux or Mac) - pico server.js - ``` - - ```JavaScript - var axios = require('axios'); - var express = require('express'); - var hana = require('@sap/hana-client'); - var app = express(); - - const VCAP_SERVICES = JSON.parse(process.env.VCAP_SERVICES); - const conSrvCred = VCAP_SERVICES.connectivity[0].credentials; - - app.get('/', function (req, res) { - res.send('Hello World'); - }) - - app.get('/Customers', async function (req, res) { - const connJwtToken = await _fetchJwtToken(conSrvCred.token_service_url, conSrvCred.clientid, conSrvCred.clientsecret); - - var connOptions = { - serverNode: 'v-linux-bj72:39015', // Virtual host specified in the Cloud Connector - proxyUsername: connJwtToken, - proxyPort: conSrvCred.onpremise_socks5_proxy_port, - proxyHostname: conSrvCred.onpremise_proxy_host, - //proxyScpAccount: 'myLocID', // Cloud Connector's location ID if specified in the Cloud Connector - // A location ID is used when multiple Cloud Connectors are connected to the same subaccount - UID: 'USER1', - PWD: 'Password1' - //traceFile: 'stdout', - //traceOptions: 'sql=warning' - }; - - var connection = hana.createConnection(); - connection.connect(connOptions, function(err) { - if (err) { - return console.error(err); - } - var sql = 'select * from HOTELS.CUSTOMER;'; - var rows = connection.exec(sql, function(err, rows) { - if (err) { - return console.error(err); - } - console.log(rows); - res.send(rows); - connection.disconnect(function(err) { - if (err) { - return console.error(err); - } - }); - }); - }); - }) - - const port = process.env.PORT || 3000; - var server = app.listen(port, function () { - var host = server.address().address - var port = server.address().port - console.log("Example app listening at http://%s:%s", host, port) - }) - - const _fetchJwtToken = async function(oauthUrl, oauthClient, oauthSecret) { - return new Promise ((resolve, reject) => { - const tokenUrl = oauthUrl + '/oauth/token?grant_type=client_credentials&response_type=token' - const config = { - headers: { - Authorization: "Basic " + Buffer.from(oauthClient + ':' + oauthSecret).toString("base64") - } - } - axios.get(tokenUrl, config) - .then(response => { - resolve(response.data.access_token) - }) - .catch(error => { - reject(error) - }) - }) - } - ``` + [OPTION BEGIN [Windows]] + + ```Shell + notepad server.js + ``` + + [OPTION END] + + [OPTION BEGIN [Linux and Mac]] + + ```Shell + pico server.js + ``` + + [OPTION END] + + ```JavaScript + var axios = require('axios'); + var express = require('express'); + var hana = require('@sap/hana-client'); + var app = express(); + + const VCAP_SERVICES = JSON.parse(process.env.VCAP_SERVICES); + const conSrvCred = VCAP_SERVICES.connectivity[0].credentials; + + app.get('/', function (req, res) { + res.send('Hello World'); + }) + + app.get('/Customers', async function (req, res) { + const connJwtToken = await _fetchJwtToken(conSrvCred.token_service_url, conSrvCred.clientid, conSrvCred.clientsecret); + + var connOptions = { + serverNode: 'v-linux-bj72:39015', // Virtual host specified in the Cloud Connector + proxyUsername: connJwtToken, + proxyPort: conSrvCred.onpremise_socks5_proxy_port, + proxyHostname: conSrvCred.onpremise_proxy_host, + //proxyScpAccount: 'myLocID', // Cloud Connector's location ID if specified in the Cloud Connector + // A location ID is used when multiple Cloud Connectors are connected to the same subaccount + UID: 'USER1', + PWD: 'Password1' + //traceFile: 'stdout', + //traceOptions: 'sql=warning' + }; + + var connection = hana.createConnection(); + connection.connect(connOptions, function(err) { + if (err) { + return console.error(err); + } + var sql = 'select * from HOTELS.CUSTOMER;'; + var rows = connection.exec(sql, function(err, rows) { + if (err) { + return console.error(err); + } + console.log(rows); + res.send(rows); + connection.disconnect(function(err) { + if (err) { + return console.error(err); + } + }); + }); + }); + }) + + const port = process.env.PORT || 3000; + var server = app.listen(port, function () { + var host = server.address().address + var port = server.address().port + console.log("Example app listening at http://%s:%s", host, port) + }) + + const _fetchJwtToken = async function(oauthUrl, oauthClient, oauthSecret) { + return new Promise ((resolve, reject) => { + const tokenUrl = oauthUrl + '/oauth/token?grant_type=client_credentials&response_type=token' + const config = { + headers: { + Authorization: "Basic " + Buffer.from(oauthClient + ':' + oauthSecret).toString("base64") + } + } + axios.get(tokenUrl, config) + .then(response => { + resolve(response.data.access_token) + }) + .catch(error => { + reject(error) + }) + }) + } + ``` 6. Redeploy the app. - ```Shell - cd .. - cf push - ``` + ```Shell + cd .. + cf push + ``` 7. The application running in the cloud, is now accessing data from an on-premise SAP HANA instance. diff --git a/tutorials/hana-clients-choose-hana-instance/hana-clients-choose-hana-instance.md b/tutorials/hana-clients-choose-hana-instance/hana-clients-choose-hana-instance.md index e7632f610..8c034eb93 100644 --- a/tutorials/hana-clients-choose-hana-instance/hana-clients-choose-hana-instance.md +++ b/tutorials/hana-clients-choose-hana-instance/hana-clients-choose-hana-instance.md @@ -4,7 +4,7 @@ author_name: Dan van Leeuwen author_profile: https://github.com/danielva auto_validation: true time: 20 -tags: [ tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana] +tags: [tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana] primary_tag: software-product>sap-hana-cloud --- @@ -28,11 +28,12 @@ This tutorial covers how to configure an [SAP HANA](https://www.sap.com/products For more information on SAP HANA Cloud, consult [Introduction to SAP HANA Cloud](https://help.sap.com/docs/hana-cloud/feature-scope-description-for-sap-hana-cloud-3dd959f1b8574cb0ba19ab05cfc0d3ae/introduction-to-sap-hana-cloud). ->For connections from additional sources such as SAP Analytics Cloud, `Jupyter` Notebooks, SAP Business Warehouse, SAP Data Intelligence Cloud, and SAP ERP Central Component see [Connection Guides for SAP HANA Cloud](group.hana-cloud-database-connection-guides). +> [!NOTE] For connections from additional sources such as SAP Analytics Cloud, `Jupyter` Notebooks, SAP Business Warehouse, SAP Data Intelligence Cloud, and SAP ERP Central Component see [Connection Guides for SAP HANA Cloud](group.hana-cloud-database-connection-guides). > >For connections to the SAP HANA Cloud, Data Lake, see the tutorial [Use Clients to Query Data Lake Relational Engine](group.hana-cloud-clients-data-lake). -> ->**IMPORTANT**: Complete the first 3 tutorials, and then you can select any of the following tutorials about connecting with different client interfaces. + +> [!TIP] +> Complete the first 3 tutorials, and then you can select any of the following tutorials about connecting with different client interfaces. --- @@ -49,15 +50,15 @@ There are multiple versions of SAP HANA. The information below is a list of lin Here are a few benefits of using SAP HANA Cloud: -- Software updates are automatically applied by SAP. +- Software updates are automatically applied by SAP -- Hardware is managed by a cloud provider (e.g. AWS, Azure, or GCP). +- Hardware is managed by a cloud provider (e.g. AWS, Azure, or GCP) - Many data center locations to choose from as listed in the [SAP Discovery Center](https://discovery-center.cloud.sap/serviceCatalog/sap-hana-cloud?region=all&tab=service_plan) -- [Backups](https://help.sap.com/docs/hana-cloud/sap-hana-cloud-administration-guide/backup-and-recovery) are automatic and recovery can be initiated in SAP HANA Cloud Central. +- [Backups](https://help.sap.com/docs/hana-cloud/sap-hana-cloud-administration-guide/backup-and-recovery) are automatic and recovery can be initiated in SAP HANA Cloud Central -- The memory, compute and storage settings can be changed as your needs change. Note a few operations can be performed using [service requests](https://help.sap.com/docs/hana-cloud/sap-hana-cloud-administration-guide/service-requests). +- The memory, compute and storage settings can be changed as your needs change. Note a few operations can be performed using [service requests](https://help.sap.com/docs/hana-cloud/sap-hana-cloud-administration-guide/service-requests) - The ability is provided to expand data storage from in-memory, to native storage extensions, to a data lake, while providing a common access layer that enables you to have further control over performance and cost. See also [Lower Your Data Management Costs With SAP HANA Cloud](https://blogs.sap.com/2019/10/29/lower-your-data-management-costs-with-sap-hana-cloud/). @@ -99,9 +100,10 @@ Continue with this tutorial once you have created an SAP HANA Cloud instance as 1. Once the SAP HANA Cloud instance is created, take note of the SQL endpoint (host:port) needed to connect to the database. The endpoint can be obtained within the Actions menu on the Instances page. This will be needed in subsequent tutorials in the mission. - ![SQL Endpoint](SQLEndpoint.png) + ![SQL endpoint](SQLEndpoint.png) - >The SAP HANA Cloud, HANA database free tier instances are shut down on a nightly basis and will need to be restarted before working with them the next day. + > [!NOTE] + > The SAP HANA Cloud, HANA database free tier instances are shut down on a nightly basis and will need to be restarted before working with them the next day. 2. From the Actions menu, Open a SQL console for your database instance. @@ -113,31 +115,31 @@ Continue with this tutorial once you have created an SAP HANA Cloud instance as 3. Run the following query to see the name of the database you are currently connected to. - ```SQL - SELECT * FROM M_DATABASE; - ``` + ```SQL + SELECT * FROM M_DATABASE; + ``` - ![Database Explorer Result](m-database.png) + ![SQL query in the SQL console](m-database.png) 4. A schema is a container for other database objects such as tables and views and the current schema can be seen via SQL as shown below. The DUMMY table is available in every HANA database that has one column and one row. It provides a convenient way to call a function or perform a simple test. - ```SQL - SELECT CURRENT_USER, CURRENT_SCHEMA FROM DUMMY; - ``` + ```SQL + SELECT CURRENT_USER, CURRENT_SCHEMA FROM DUMMY; + ``` ![SQL console results](select-user-schema.png) 5. To see the list of services, enter the following SQL statement: - ```SQL - SELECT * FROM M_SERVICES; - ``` + ```SQL + SELECT * FROM M_SERVICES; + ``` 6. To see information about the database server, enter the following SQL statement: - ```SQL - SELECT * FROM M_HOST_INFORMATION; - ``` + ```SQL + SELECT * FROM M_HOST_INFORMATION; + ``` >Views starting with `M_` are examples of [monitoring views](https://help.sap.com/docs/hana-cloud-database/sap-hana-cloud-sap-hana-database-sql-reference-guide/monitoring-views) and contain statistics and status details. @@ -157,39 +159,33 @@ The following steps will demonstrate connecting to and examining a SAP HANA on p 1. Enter the following to connect to the system database: - ```Shell - hdbsql -n localhost:39013 -u SYSTEM -p Your_Password - ``` + ```Shell + hdbsql -n localhost:39013 -u SYSTEM -p Your_Password + ``` ![hdbsql connected](hdbsql-connect.png) Notice that the database being connected to is SYSTEMDB. - The example above uses localhost since hdbsql is running on the same machine that the database is trying to connect to. The host name, `hxehost`, is seen in the terminal above. - - >If hdbsql is not found and you are logged in with another user, try connecting as the user `hxeadm` and run the command again. - - ```Shell - su hxeadm - ``` + The example above uses localhost since hdbsql is running on the same machine that the database is trying to connect to. If the hdbsql command cannot be found, simply read through the following examples. The installation and further examples of running HDBSQL will be covered in subsequent tutorials. 2. Determine the IP address of the machine that is running SAP HANA on premise. Record the value as it will be needed in later tutorials in the mission. It is important to note the IP address or host name of the machine, as this will be needed in later tutorials. - ```Shell - ip addr - ``` + ```Shell + ip addr + ``` 3. The following are a some examples of [interactive options](https://help.sap.com/docs/SAP_HANA_CLIENT/f1b440ded6144a54ada97ff95dac7adf/c24d054bbb571014b253ac5d6943b5bd.html) followed by a SQL query, which when run against **SYSTEMDB** returns information about the databases running on the SAP HANA instance. - ```SQL - \al on - \pa off - \s - SELECT * FROM SYS_DATABASES.M_SERVICES WHERE SQL_PORT != 0; - \serverstats - ``` + ```SQL + \al on + \pa off + \s + SELECT * FROM SYS_DATABASES.M_SERVICES WHERE SQL_PORT != 0; + \serverstats + ``` ![hdbsql commands](hdbsql-commands.png) @@ -207,22 +203,22 @@ The following steps will demonstrate connecting to and examining a SAP HANA on p 4. Enter one of the below commands to exit from viewing the results of the select statement. Note that commands can be prefixed with a forward slash(\\) or a colon(:). - ```HDBSQL - \q - :q - ``` + ```HDBSQL + \q + :q + ``` 5. Connect using the instance number and database name as shown below. - ```Shell - hdbsql -n localhost -i 90 -d HXE -u SYSTEM -p Your_Password - ``` + ```Shell + hdbsql -n localhost -i 90 -d HXE -u SYSTEM -p Your_Password + ``` 6. Enter the following to display database connection information. - ```HDBSQL - \s - ``` + ```HDBSQL + \s + ``` Notice that this time the database connected to is HXE. @@ -234,4 +230,4 @@ The following steps will demonstrate connecting to and examining a SAP HANA on p Congratulations! You now have access to an SAP HANA instance and understand some of the differences between SAP HANA Cloud and SAP HANA on premise. ---- \ No newline at end of file +--- diff --git a/tutorials/hana-clients-dot-net-core/hana-clients-dot-net-core.md b/tutorials/hana-clients-dot-net-core/hana-clients-dot-net-core.md index d0969ae63..30ac4bdcb 100644 --- a/tutorials/hana-clients-dot-net-core/hana-clients-dot-net-core.md +++ b/tutorials/hana-clients-dot-net-core/hana-clients-dot-net-core.md @@ -4,7 +4,7 @@ author_name: Dan van Leeuwen author_profile: https://github.com/danielva auto_validation: true time: 15 -tags: [ tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana] +tags: [tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana] primary_tag: software-product>sap-hana-cloud --- @@ -39,114 +39,131 @@ If the `dotnet` command is not recognized, it means that the .NET SDK has not be If the .NET SDK is not installed, download it from [Download .NET](https://dotnet.microsoft.com/download) and run the installer on Microsoft Windows or Mac. -![.NET Core SDK Install](dotnet-install.png) +![.NET Core SDK install](dotnet-install.png) On Linux, follow the instructions for the appropriate Linux version such as [Install the .NET SDK or the .NET Runtime on openSUSE](https://docs.microsoft.com/en-us/dotnet/core/install/linux-opensuse). In order for the shell to recognize that the .NET SDK is installed and for any `dotnet` commands in future steps to be recognized, a new shell window needs to be opened. ->For further details on supported versions, see SAP Note [3165810 - SAP HANA Client Supported Platforms](https://launchpad.support.sap.com/#/notes/3165810). +> [!NOTE] +> For further details on supported versions, see SAP Note 3165810 - SAP HANA Client Supported Platforms. ### Create a .NET application that queries an SAP HANA database 1. Create a new console app with the below commands: - ```Shell (Microsoft Windows) - cd %HOMEPATH%/HANAClientsTutorial - dotnet new console -o dotNET - ``` + [OPTION BEGIN [Windows]] - ```Shell (Linux or Mac) - cd $HOME/HANAClientsTutorial - dotnet new console -o dotNET - ``` + ```Shell + cd %HOMEPATH%/HANAClientsTutorial + dotnet new console -o dotNET + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + cd $HOME/HANAClientsTutorial + dotnet new console -o dotNET + ``` + + [OPTION END] 2. Add the SAP HANA .NET data provider which is available on [nuget](https://www.nuget.org/packages/Sap.Data.Hana.Net.v8.0/). A list of available providers from SAP is available at [SAP-SE](https://www.nuget.org/profiles/SAP-SE). - ```Shell - cd dotNET - dotnet add package Sap.Data.Hana.Net.v8.0 - ``` + ```Shell + cd dotNET + dotnet add package Sap.Data.Hana.Net.v8.0 + ``` - ![HANAClientDriverDownload](HANAClientDriver.png) + ![HANA Client download](HANAClientDriver.png) 3. Run the app to validate that SAP HANA driver can be loaded: - ```Shell - dotnet run - ``` + ```Shell + dotnet run + ``` 4. Open an editor to edit the file `Program.cs`. - ```Shell (Windows) - notepad Program.cs - ``` + [OPTION BEGIN [Windows]] + + ```Shell + notepad Program.cs + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + pico Program.cs + ``` - ```Shell (Linux or Mac) - pico Program.cs - ``` + [OPTION END] 5. Replace all content of `Program.cs` with the code below. Be sure to update values where necessary and save the file when finished. - ```C# - using System; - using Sap.Data.Hana; - namespace dotNETQuery - { - class Program - { - static void Main(string[] args) - { - try - { - using (var conn = new HanaConnection("Server=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx.hana.prod-xxxx.hanacloud.ondemand.com:443;UID=User1;PWD=Password1;encrypt=true;sslValidateCertificate=false")) - - // encrypt and sslValidateCertificate should be true for HANA Cloud connections - // As of SAP HANA Client 2.6, connections on port 443 enable encryption by default - // sslValidateCertificate should be set to false when connecting - // to an on-premise SAP HANA instance that uses a self-signed certificate. - - { - conn.Open(); - Console.WriteLine("Connected"); - var query = "SELECT TITLE, FIRSTNAME, NAME FROM HOTELS.CUSTOMER"; - using (var cmd = new HanaCommand(query, conn)) - using (var reader = cmd.ExecuteReader()) - { - Console.WriteLine("Query result:"); - // Print column names - var sbCol = new System.Text.StringBuilder(); - for (var i = 0; i < reader.FieldCount; i++) - { - sbCol.Append(reader.GetName(i).PadRight(20)); - } - Console.WriteLine(sbCol.ToString()); - // Print rows - while (reader.Read()) - { - var sbRow = new System.Text.StringBuilder(); - for (var i = 0; i < reader.FieldCount; i++) - { - var result = reader[i].ToString(); - if (result is not null) { - sbRow.Append(result.PadRight(20)); - } - } - Console.WriteLine(sbRow.ToString()); - } - conn.Close(); - } - } - } - catch (Exception ex) - { - Console.WriteLine("Error - " + ex.Message); - Console.WriteLine(ex.ToString()); - } - } - } - } - ``` + ```C# + using System; + using Sap.Data.Hana; + namespace dotNETQuery + { + class Program + { + static void Main(string[] args) + { + try + { + using (var conn = new HanaConnection("Server=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx.hana.prod-xxxx.hanacloud.ondemand.com:443;UID=User1;PWD=Password1;encrypt=true;sslValidateCertificate=false")) + + // encrypt and sslValidateCertificate should be true for HANA Cloud connections + // As of SAP HANA Client 2.6, connections on port 443 enable encryption by default + // sslValidateCertificate should be set to false when connecting + // to an on-premise SAP HANA instance that uses a self-signed certificate. + + { + conn.Open(); + Console.WriteLine("Connected"); + var query = "SELECT TITLE, FIRSTNAME, NAME FROM HOTELS.CUSTOMER"; + using (var cmd = new HanaCommand(query, conn)) + using (var reader = cmd.ExecuteReader()) + { + Console.WriteLine("Query result:"); + // Print column names + var sbCol = new System.Text.StringBuilder(); + for (var i = 0; i < reader.FieldCount; i++) + { + sbCol.Append(reader.GetName(i).PadRight(20)); + } + Console.WriteLine(sbCol.ToString()); + // Print rows + while (reader.Read()) + { + var sbRow = new System.Text.StringBuilder(); + for (var i = 0; i < reader.FieldCount; i++) + { + var result = reader[i].ToString(); + if (result is not null) { + sbRow.Append(result.PadRight(20)); + } + } + Console.WriteLine(sbRow.ToString()); + } + conn.Close(); + } + } + } + catch (Exception ex) + { + Console.WriteLine("Error - " + ex.Message); + Console.WriteLine(ex.ToString()); + } + } + } + } + ``` Save and close the `Program.cs` file after replacing the code and updating the host and port. @@ -154,11 +171,12 @@ In order for the shell to recognize that the .NET SDK is installed and for any ` 6. Run the app: - ```Shell - dotnet run - ``` + ```Shell + dotnet run + ``` - >Before running the program make sure to be in the directory where Program.cs is saved + > [!TIP] + > Before running the program, make sure to be in the directory where Program.cs is saved. ![Result of running the app](result.png) @@ -186,7 +204,7 @@ In order for the shell to recognize that the .NET SDK is installed and for any ` Observe the variable values in the leftmost pane. Step through code. - ![VS Code Debugging](debugging.png) + ![Visual Studio Code debugging](debugging.png) For further information on debugging .NET apps consult [Tutorial: Debug a .NET Core console application using Visual Studio Code](https://docs.microsoft.com/en-us/dotnet/core/tutorials/debugging-with-visual-studio-code) and [Instructions for setting up the .NET Core debugger](https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger.md). diff --git a/tutorials/hana-clients-entity-framework/hana-clients-entity-framework.md b/tutorials/hana-clients-entity-framework/hana-clients-entity-framework.md index 798717b7e..b3517776a 100644 --- a/tutorials/hana-clients-entity-framework/hana-clients-entity-framework.md +++ b/tutorials/hana-clients-entity-framework/hana-clients-entity-framework.md @@ -4,7 +4,7 @@ author_name: Dan van Leeuwen author_profile: https://github.com/danielva auto_validation: true time: 15 -tags: [ tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana] +tags: [tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana] primary_tag: software-product>sap-hana-cloud --- @@ -59,127 +59,155 @@ The help for the .NET Command Line Tools can be displayed as shown below. dotnet ef -h ``` -![entity framework tools](entity-framework-tools.png) +![Entity framework tools](entity-framework-tools.png) ### Create a .NET Core EF application that queries an SAP HANA database 1. Create a new console app with the below commands: - ```Shell (Microsoft Windows) - cd %HOMEPATH%/HANAClientsTutorial - dotnet new console -o EFCore - ``` + [OPTION BEGIN [Windows]] - ```Shell (Linux or Mac) - cd $HOME/HANAClientsTutorial - dotnet new console -o EFCore - ``` + ```Shell + cd %HOMEPATH%/HANAClientsTutorial + dotnet new console -o EFCore + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + cd $HOME/HANAClientsTutorial + dotnet new console -o EFCore + ``` + + [OPTION END] 2. Add the required packages including the SAP HANA .NET data provider which is available on [nuget](https://www.nuget.org/packages/Sap.EntityFrameworkCore.Hana.v9.0). A list of available providers from SAP is available at [SAP-SE](https://www.nuget.org/profiles/SAP-SE). - ```Shell - cd EFCore - dotnet add package Sap.EntityFrameworkCore.Hana.v9.0 - dotnet add package Microsoft.EntityFrameworkCore.Relational --version 9.0.14 - ``` + ```Shell + cd EFCore + dotnet add package Sap.EntityFrameworkCore.Hana.v9.0 + dotnet add package Microsoft.EntityFrameworkCore.Relational --version 9.0.14 + ``` - ![HANAClientDriverDownload](HANAClientDriver.png) + ![HANA Client download](HANAClientDriver.png) The packages can be listed using the command below. - ```Shell - dotnet list package - ``` + ```Shell + dotnet list package + ``` 3. Run the app to validate that SAP hdbclient DLLs can be loaded: - ```Shell - dotnet run - ``` + ```Shell + dotnet run + ``` The expected output is `Hello, World!`. 4. Open an editor and create a file named `HotelModel.cs`. - ```Shell (Windows) - notepad HotelModel.cs - ``` + [OPTION BEGIN [Windows]] + + ```Shell + notepad HotelModel.cs + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + pico HotelModel.cs + ``` - ```Shell (Linux or Mac) - pico HotelModel.cs - ``` + [OPTION END] 5. Copy the below code into `HotelModel.cs` with the code below: - ```C# - using Microsoft.EntityFrameworkCore; - using Sap.EntityFrameworkCore.Hana; + ```C# + using Microsoft.EntityFrameworkCore; + using Sap.EntityFrameworkCore.Hana; - public class HotelContext : DbContext - { - public DbSet Hotel { get; set; } + public class HotelContext : DbContext + { + public DbSet Hotel { get; set; } - public HotelContext() - { - var folder = Environment.SpecialFolder.LocalApplicationData; - var path = Environment.GetFolderPath(folder); + public HotelContext() + { + var folder = Environment.SpecialFolder.LocalApplicationData; + var path = Environment.GetFolderPath(folder); - Database.EnsureDeleted(); - Database.EnsureCreated(); - } + Database.EnsureDeleted(); + Database.EnsureCreated(); + } - protected override void OnConfiguring(DbContextOptionsBuilder options) { - options.UseHana("Server=xxxxxxxx-.hanacloud.ondemand.com:443;UserName=User2;Password=Password2;Current Schema=USER2"); - } - } + protected override void OnConfiguring(DbContextOptionsBuilder options) { + options.UseHana("Server=xxxxxxxx-.hanacloud.ondemand.com:443;UserName=User2;Password=Password2;Current Schema=USER2"); + } + } - public class HotelEF - { - public int Id { get; set; } = 0; - public string Name { get; set; } = string.Empty; - public string Address { get; set; } = string.Empty; - } - ``` + public class HotelEF + { + public int Id { get; set; } = 0; + public string Name { get; set; } = string.Empty; + public string Address { get; set; } = string.Empty; + } + ``` - Be sure to update the host URL and optionally the user name and password. Note that calls to EnsureDeleted and EnsureCreated will delete and recreate the objects in the schema USER2. As documented at [RelationalDatabaseCreator.EnsureDeleted Method](https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.storage.relationaldatabasecreator.ensuredeleted), it will delete all objects in the schema USER2. + Be sure to update the host URL and optionally the user name and password. + + > [!WARNING] + > EnsureDeleted and EnsureCreated will delete and recreate the objects in the schema USER2. As documented at [RelationalDatabaseCreator.EnsureDeleted Method](https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.storage.relationaldatabasecreator.ensuredeleted), it will delete all objects in the schema USER2. 6. Open an editor to edit the file `Program.cs`. - ```Shell (Windows) - notepad Program.cs - ``` + [OPTION BEGIN [Windows]] + + ```Shell + notepad Program.cs + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] - ```Shell (Linux or Mac) - pico Program.cs - ``` + ```Shell + pico Program.cs + ``` + + [OPTION END] 7. Replace the entire contents of `Program.cs` with the code below. Save and close the file when finished. - ```C# - using var db = new HotelContext(); + ```C# + using var db = new HotelContext(); - // Create - Console.WriteLine("Inserting a new Hotel"); - db.Add(new HotelEF { Id = 1, Name = "The Inn of Waterloo", Address = "475 King St N, Waterloo" }); - db.Add(new HotelEF { Id = 2, Name = "The Walper Hotel", Address = "20 Queen St S, Kitchener" }); - db.SaveChanges(); + // Create + Console.WriteLine("Inserting a new Hotel"); + db.Add(new HotelEF { Id = 1, Name = "The Inn of Waterloo", Address = "475 King St N, Waterloo" }); + db.Add(new HotelEF { Id = 2, Name = "The Walper Hotel", Address = "20 Queen St S, Kitchener" }); + db.SaveChanges(); - // Read - Console.WriteLine("Querying for a hotel"); - var hotels = db.Hotel - .OrderBy(b => b.Name).Last(); - Console.WriteLine("Found: " + hotels.Name); - ``` + // Read + Console.WriteLine("Querying for a hotel"); + var hotels = db.Hotel + .OrderBy(b => b.Name).Last(); + Console.WriteLine("Found: " + hotels.Name); + ``` Further details on SAP HANA Client entity core driver can be found at [Entity Framework Core Support](https://help.sap.com/docs/SAP_HANA_CLIENT/f1b440ded6144a54ada97ff95dac7adf/3e6ef454ffc94cda8fefb0acf5be007b.html). Further .NET API details can be found in the [.NET API browser](https://learn.microsoft.com/en-us/dotnet/api/?view=efcore-6.0). 8. Run the app: - ```Shell - dotnet run - ``` + ```Shell + dotnet run + ``` - >Before running the program make sure to be in the directory where Program.cs is saved + > [!TIP] + > Before running the program, make sure you are in the directory where `Program.cs` is saved. ![Result of running the app](result.png) @@ -201,7 +229,7 @@ dotnet ef -h Observe the variable values in the leftmost pane. Step through code. - ![VS Code Debugging](debugging.png) + ![Visual Studio Code debugging](debugging.png) For further information on debugging .NET apps consult [Tutorial: Debug a .NET Core console application using Visual Studio Code](https://docs.microsoft.com/en-us/dotnet/core/tutorials/debugging-with-visual-studio-code) and [Instructions for setting up the .NET Core debugger](https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger.md). @@ -211,135 +239,168 @@ The following steps demonstrate the process of generating entity type classes an 1. Create a new console app with the below commands: - ```Shell (Microsoft Windows) - cd %HOMEPATH%/HANAClientsTutorial - dotnet new console -o EFCoreScaffold - ``` + [OPTION BEGIN [Windows]] + + ```Shell + cd %HOMEPATH%/HANAClientsTutorial + dotnet new console -o EFCoreScaffold + ``` + + [OPTION END] - ```Shell (Linux or Mac) - cd $HOME/HANAClientsTutorial - dotnet new console -o EFCoreScaffold - ``` + [OPTION BEGIN [Mac and Linux]] + + ```Shell + cd $HOME/HANAClientsTutorial + dotnet new console -o EFCoreScaffold + ``` + + [OPTION END] 2. Install the required packages. - ```Shell - cd EFCoreScaffold - dotnet add package Sap.EntityFrameworkCore.Hana.v9.0 - dotnet add package Microsoft.EntityFrameworkCore.Relational --version 9.0.14 - dotnet add package Microsoft.EntityFrameworkCore.Design --version 9.0.14 - ``` + ```Shell + cd EFCoreScaffold + dotnet add package Sap.EntityFrameworkCore.Hana.v9.0 + dotnet add package Microsoft.EntityFrameworkCore.Relational --version 9.0.14 + dotnet add package Microsoft.EntityFrameworkCore.Design --version 9.0.14 + ``` The list of installed packages can be seen using the below command. - ```Shell - dotnet list package - ``` + ```Shell + dotnet list package + ``` - ![package list](package-list.png) + ![Package list](package-list.png) Additional details can be found at [dotnet add package](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-add-package) and [Microsoft.EntityFrameworkCore.Design](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Design) 3. Use the scaffold command to generate entity classes for the HOTELS schema. Update the SQL endpoint. - ```Shell - dotnet ef dbcontext scaffold "Server=xxxxxxxx-.hanacloud.ondemand.com:443;uid=USER2;pwd=Password2;Current Schema=HOTELS" Sap.EntityFrameworkCore.Hana.v9.0 --schema HOTELS --context HotelsContext - ``` + ```Shell + dotnet ef dbcontext scaffold "Server=xxxxxxxx-.hanacloud.ondemand.com:443;uid=USER2;pwd=Password2;Current Schema=HOTELS" Sap.EntityFrameworkCore.Hana.v9.0 --schema HOTELS --context HotelsContext + ``` Notice that classes have been generated for each object in the schema HOTELS. - ![scaffold command](scaffold.png) + ![Scaffold command](scaffold.png) - Should you wish to regenerate the files in the future and overwrite the existing files, the `--force` parameter can be used. Additional details on the scaffold command can be found at [.NET Core CLI](https://learn.microsoft.com/en-us/ef/core/cli/dotnet#dotnet-ef-dbcontext-scaffold). + > [!NOTE] + > Should you wish to regenerate the files in the future and overwrite the existing files, the `--force` parameter can be used. Additional details on the scaffold command can be found at [.NET Core CLI](https://learn.microsoft.com/en-us/ef/core/cli/dotnet#dotnet-ef-dbcontext-scaffold). 4. Open an editor to edit the file `Program.cs`. - ```Shell (Windows) - notepad Program.cs - ``` + [OPTION BEGIN [Windows]] + + ```Shell + notepad Program.cs + ``` + + [OPTION END] - ```Shell (Linux or Mac) - pico Program.cs - ``` + [OPTION BEGIN [Mac and Linux]] + + ```Shell + pico Program.cs + ``` + + [OPTION END] 5. Replace the entire contents of `Program.cs` with the code below. Save and close the file when finished. - ```C# - using EFCoreScaffold; + ```C# + using EFCoreScaffold; - using var db = new MyHotelsContext(true); + using var db = new MyHotelsContext(true); - // Create - Console.WriteLine("Inserting a new maintenance item"); - db.Add(new Maintenance { Mno = 3, Description = "Replace cracked mirror in lobby bathroom" }); - db.SaveChanges(); + // Create + Console.WriteLine("Inserting a new maintenance item"); + db.Add(new Maintenance { Mno = 3, Description = "Replace cracked mirror in lobby bathroom" }); + db.SaveChanges(); - // Read - Console.WriteLine("Querying for a maintenance item"); - var maintenanceItems = db.Maintenances - .OrderBy(b => b.Hno).Last(); - Console.WriteLine("Found item#: " + maintenanceItems.Mno + " Desc: " + maintenanceItems.Description); - ``` + // Read + Console.WriteLine("Querying for a maintenance item"); + var maintenanceItems = db.Maintenances + .OrderBy(b => b.Hno).Last(); + Console.WriteLine("Found item#: " + maintenanceItems.Mno + " Desc: " + maintenanceItems.Description); + ``` 6. Open an editor to edit the file `HotelsContext.cs`. - ```Shell (Windows) - notepad HotelsContext.cs - ``` + [OPTION BEGIN [Windows]] + + ```Shell + notepad HotelsContext.cs + ``` - ```Shell (Linux or Mac) - pico HotelsContext.cs - ``` + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + pico HotelsContext.cs + ``` + + [OPTION END] 7. Delete the `OnConfiguring` method. This will be added to the `MyHotelsContext.cs` class. 8. Open an editor to create and edit a new file named `MyHotelsContext.cs`. - ```Shell (Windows) - notepad MyHotelsContext.cs - ``` + [OPTION BEGIN [Windows]] + + ```Shell + notepad MyHotelsContext.cs + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + pico MyHotelsContext.cs + ``` - ```Shell (Linux or Mac) - pico MyHotelsContext.cs - ``` + [OPTION END] 9. Add the code below. Update the Server= line to match your SAP HANA Cloud SQL endpoint. Save and close the file when finished. Note that the schema is changed to be USER2. - ```C# - using Microsoft.EntityFrameworkCore; - using Sap.EntityFrameworkCore.Hana; - - namespace EFCoreScaffold; - internal class MyHotelsContext : HotelsContext - { - public MyHotelsContext(bool createTables) : base() - { - if (createTables) - { - // Delete the existing database tables and re-create new tables. - Database.EnsureDeleted(); - Database.EnsureCreated(); - } - } - - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - optionsBuilder.UseHana("Server=xxxxxxxx-.hanacloud.ondemand.com:443;uid=USER2;pwd=Password2;Current Schema=USER2"); - } - } - ``` + ```C# + using Microsoft.EntityFrameworkCore; + using Sap.EntityFrameworkCore.Hana; + + namespace EFCoreScaffold; + internal class MyHotelsContext : HotelsContext + { + public MyHotelsContext(bool createTables) : base() + { + if (createTables) + { + // Delete the existing database tables and re-create new tables. + Database.EnsureDeleted(); + Database.EnsureCreated(); + } + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseHana("Server=xxxxxxxx-.hanacloud.ondemand.com:443;uid=USER2;pwd=Password2;Current Schema=USER2"); + } + } + ``` 10. Run the app: - ```Shell - dotnet run - ``` + ```Shell + dotnet run + ``` - ![Result of running the app](results2.png) + ![Result of running the app](results2.png) - Notice that tables such as CUSTOMER, HOTEL, MAINTENANCE etc have now been created in the USER2 schema. + Notice that tables such as CUSTOMER, HOTEL, MAINTENANCE etc have now been created in the USER2 schema. - ![tables in user2 schema](Tables-in-USER2-schema.png) + ![Tables in user2 schema](Tables-in-USER2-schema.png) ### Knowledge check diff --git a/tutorials/hana-clients-golang/hana-clients-golang.md b/tutorials/hana-clients-golang/hana-clients-golang.md index b69c6d343..27cc7a051 100644 --- a/tutorials/hana-clients-golang/hana-clients-golang.md +++ b/tutorials/hana-clients-golang/hana-clients-golang.md @@ -4,7 +4,7 @@ author_name: Dan van Leeuwen author_profile: https://github.com/danielva auto_validation: true time: 15 -tags: [ tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana] +tags: [tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana] primary_tag: software-product>sap-hana-cloud --- @@ -39,13 +39,15 @@ go version If Go is installed, then it will return the currently installed version, such as 1.22.1. ->For further details on supported versions, see SAP Note [3165810 - SAP HANA Client Supported Platforms](https://launchpad.support.sap.com/#/notes/3165810). +> [!NOTE] +> For further details on supported versions, see SAP Note [3165810 - SAP HANA Client Supported Platforms](https://launchpad.support.sap.com/#/notes/3165810). If it is not installed, download it from [Download Go](https://golang.org/dl/), run the installer, follow the provided instructions, and ensure that Go is in your path. On Linux, follow the instructions for the appropriate Linux version such as the [Installing Go for openSUSE](https://en.opensuse.org/SDB:Go). ->In order for the shell to recognize that Go has been installed and for any go commands in future steps to be recognized, a new shell window needs to be opened. +> [!TIP] +> In order for the shell to recognize that Go has been installed and for any go commands in future steps to be recognized, a new shell window needs to be opened. ### Configure the environment @@ -53,33 +55,33 @@ The SAP HANA Client interface for Go, like the other SAP HANA client interfaces, 1. To check if a 64-bit `gcc` compiler is installed, run the following command: - ```Shell - gcc --version - ``` + ```Shell + gcc --version + ``` ![gcc 64-bit](gccLinux.png) For Windows (if it is not installed), it can be downloaded from [Download MinGW](https://www.mingw-w64.org/downloads/). Under **WinLibs.com**, you can install from [winlibs.com](https://winlibs.com/), by scrolling to the **Download** section and downloading the latest release version (UCRT runtime) of the ZIP archive for Win64 to install for the x86_64 architecture, and then extracting the folder. - ![download minGW from WinLibs](winLibsMinGW.png) + ![Download minGW from WinLibs](winLibsMinGW.png) If command prompt isn't showing you the installed version after running the version check command, manually add the bin folder to your path by setting it in your environment variables. - >On Windows, search **Edit the System Environment Variables** and click on **Environment Variables...**. - > - ![Edit Environment Variables](editEnvironmentVariables.png) + On Windows, search **Edit the System Environment Variables** and click on **Environment Variables...**. + + ![Edit environment variables](editEnvironmentVariables.png) Look for the `Path` environment variable and double click to edit. Select **Browse** and manually browse through your File Explorer to find the bin folder. - ![Add bin to path](add-bin-to-path.png) + ![Add bin to path](add-bin-to-path.png) On Linux, install the System GNU C compiler for your version of Linux. Note that if you are using openSUSE, minGW is included in the installation for Go through YaST. 2. Examine the Go environment by running the below command: - ```Shell - go env - ``` + ```Shell + go env + ``` Notice that GOROOT is set to a location such as `C:\go` or `/usr/lib64/go/1.22`. This is the location that the Go SDK is installed to. @@ -89,39 +91,59 @@ The SAP HANA Client interface for Go, like the other SAP HANA client interfaces, On Windows, add a **NEW** variable. Set the variable name to **`CGO_LDFLAGS`** and the variable value to the location of `dbcapi` library: `C:\SAP\hdbclient\libdbcapiHDB.dll` - ![Set Environment Variables](setEnvVar.png) + ![Set environment variables](setEnvVar.png) Ensure that the `hdbclient` folder is set in your **Path** environment variable. You can set this path by clicking on **New** and browsing for your `hdbclient` folder. - ![hdbclient path env variable](hdbclient-path.png) + ![hdbclient path environment variable](hdbclient-path.png) + + [OPTION BEGIN [Mac and Linux]] On Linux and Mac, add the corresponding following lines to the `.bash_profile`. - ```Shell (Linux) - export CGO_LDFLAGS=$HOME/sap/hdbclient/libdbcapiHDB.so - export LD_LIBRARY_PATH=$HOME/sap/hdbclient - ``` + [OPTION END] - ```Shell (Mac) - export CGO_LDFLAGS="$HOME/sap/hdbclient/libdbcapiHDB.dylib" - export DYLD_LIBRARY_PATH="$HOME/sap/hdbclient" - ``` + [OPTION BEGIN [Linux]] + + ```Shell + export CGO_LDFLAGS=$HOME/sap/hdbclient/libdbcapiHDB.so + export LD_LIBRARY_PATH=$HOME/sap/hdbclient + ``` + + [OPTION END] + + [OPTION BEGIN [Mac]] + + ```Shell + export CGO_LDFLAGS="$HOME/sap/hdbclient/libdbcapiHDB.dylib" + export DYLD_LIBRARY_PATH="$HOME/sap/hdbclient" + ``` + + [OPTION END] 4. Go to the driver folder and create a go module. - ```Shell (Windows) - cd C:\SAP\hdbclient\golang\src\SAP\go-hdb\driver - go mod init "SAP/go-hdb/driver" - go mod tidy - ``` + [OPTION BEGIN [Windows]] - ```Shell (Linux or Mac) - cd ~/sap/hdbclient/golang/src/SAP/go-hdb/driver - go mod init "SAP/go-hdb/driver" - go mod tidy - ``` + ```Shell + cd C:\SAP\hdbclient\golang\src\SAP\go-hdb\driver + go mod init "SAP/go-hdb/driver" + go mod tidy + ``` - ![createModule](createModule.png) + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + cd ~/sap/hdbclient/golang/src/SAP/go-hdb/driver + go mod init "SAP/go-hdb/driver" + go mod tidy + ``` + + [OPTION END] + + ![Create module](createModule.png) The contents of the HANA Client folder is not writeable so you may need to change the permissions on the driver folder or copy files to a new location. @@ -129,103 +151,128 @@ The SAP HANA Client interface for Go, like the other SAP HANA client interfaces, 1. In a shell, create a folder named `go`, enter the newly created directory, and open a file named `goQuery.go` in an editor. - ```Shell (Microsoft Windows) - mkdir %HOMEPATH%\HANAClientsTutorial\go - cd %HOMEPATH%\HANAClientsTutorial\go - notepad goQuery.go - ``` + [OPTION BEGIN [Windows]] - ```Shell (Linux or Mac) - mkdir -p $HOME/HANAClientsTutorial/go - cd $HOME/HANAClientsTutorial/go - pico goQuery.go - ``` + ```Shell + mkdir %HOMEPATH%\HANAClientsTutorial\go + cd %HOMEPATH%\HANAClientsTutorial\go + notepad goQuery.go + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + mkdir -p $HOME/HANAClientsTutorial/go + cd $HOME/HANAClientsTutorial/go + pico goQuery.go + ``` + + [OPTION END] 2. Add the code below to `goQuery.go`: - ```Go Code - package main - - import ( - "fmt" - "database/sql" - "log" - - _ "SAP/go-hdb/driver" - ) - - func main() { - //Option 1, retrieve the connection parameters from the hdbuserstore - //host, port, user name and password come from the hdbuserstore key USER1UserKey - connectString := "hdb://?key=USER1UserKey&encrypt=true&sslValidateCertificate=false" - - //Option 2, specify the connection parameters - //connectString := "hdb://User1:Password1@999deec0-ccb7-4a5e-b317-d419e19be648.hana.prod-us10.hanacloud.ondemand.com:443?encrypt=true&sslValidateCertificate=false" - - //encrypt and sslValidateCertificate should be true for HANA Cloud connections - //As of SAP HANA Client 2.6, connections on port 443 enable encryption by default - - fmt.Println("Connect String is " + connectString) - - db, err := sql.Open("hdb", connectString) - if err != nil { - log.Fatal(err) - return - } - defer db.Close() - - rows, err := db.Query("SELECT NAME, ADDRESS from HOTELS.CUSTOMER") - if err != nil { - log.Fatal(err) - } - defer rows.Close() - - var lastName string - var address string - for rows.Next() { - err = rows.Scan(&lastName, &address) - if err != nil { - log.Fatal(err) - } - fmt.Println(lastName + ": " + address) - } - - err = rows.Err() - if err != nil { - log.Fatal(err) - } - } - ``` + ```Go Code + package main + + import ( + "fmt" + "database/sql" + "log" + + _ "SAP/go-hdb/driver" + ) + + func main() { + //Option 1, retrieve the connection parameters from the hdbuserstore + //host, port, user name and password come from the hdbuserstore key USER1UserKey + connectString := "hdb://?key=USER1UserKey&encrypt=true&sslValidateCertificate=false" + + //Option 2, specify the connection parameters + //connectString := "hdb://User1:Password1@999deec0-ccb7-4a5e-b317-d419e19be648.hana.prod-us10.hanacloud.ondemand.com:443?encrypt=true&sslValidateCertificate=false" + + //encrypt and sslValidateCertificate should be true for HANA Cloud connections + //As of SAP HANA Client 2.6, connections on port 443 enable encryption by default + + fmt.Println("Connect String is " + connectString) + + db, err := sql.Open("hdb", connectString) + if err != nil { + log.Fatal(err) + return + } + defer db.Close() + + rows, err := db.Query("SELECT NAME, ADDRESS from HOTELS.CUSTOMER") + if err != nil { + log.Fatal(err) + } + defer rows.Close() + + var lastName string + var address string + for rows.Next() { + err = rows.Scan(&lastName, &address) + if err != nil { + log.Fatal(err) + } + fmt.Println(lastName + ": " + address) + } + + err = rows.Err() + if err != nil { + log.Fatal(err) + } + } + ``` Once the `goQuery.go` file has been updated, save and close the file. 3. Create another go module and modify its contents: - ```Shell (Windows) - go mod init "go/goQuery" - go mod tidy - notepad go.mod - ``` + [OPTION BEGIN [Windows]] - ```Shell (Linux or Mac) - go mod init "go/goQuery" - go mod tidy - pico go.mod - ``` + ```Shell + go mod init "go/goQuery" + go mod tidy + notepad go.mod + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + go mod init "go/goQuery" + go mod tidy + pico go.mod + ``` + + [OPTION END] 4. Add the code below to `go.mod` under the go version line: - >Make sure the path to the driver folder is correct and make any necessary changes. + > [!TIP] + > Make sure the path to the driver folder is correct and make any necessary changes. - ```Code (Windows) - replace SAP/go-hdb/driver v0.1.0 => C:\SAP\hdbclient\golang\src\SAP\go-hdb\driver - require SAP/go-hdb/driver v0.1.0 - ``` + [OPTION BEGIN [Windows]] - ```Code (Linux or Mac) - replace SAP/go-hdb/driver v0.1.0 => /home/name/sap/hdbclient/golang/src/SAP/go-hdb/driver - require SAP/go-hdb/driver v0.1.0 - ``` + ```Code + replace SAP/go-hdb/driver v0.1.0 => C:\SAP\hdbclient\golang\src\SAP\go-hdb\driver + require SAP/go-hdb/driver v0.1.0 + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Code + replace SAP/go-hdb/driver v0.1.0 => /home/name/sap/hdbclient/golang/src/SAP/go-hdb/driver + require SAP/go-hdb/driver v0.1.0 + ``` + + [OPTION END] ![go.mod contents](goModContents.png) @@ -247,33 +294,33 @@ Visual Studio Code provides plugins for Go and can be used to debug an applicati 2. If you have not already done so, in Visual Studio Code, choose **File | Add Folder to Workspace**, and then add the `HANAClientsTutorial` folder. - ![Open Workspace](workspace.png) + ![Open the workspace](workspace.png) 3. Open the file `goQuery.go`. - ![Go Extension](GoExtension.png) + ![Go extension install](GoExtension.png) Visual Studio Code will recognize the `go` file extension and will suggest installing the Go for Visual Studio Code extension. Click **Install**. Check whether a `launch.json` file has been created. If not, go to the Run and Debug tab and select “Create a launch.json file.” - ![Go Create Json](GoCreateJson.png) + ![Create a launch](GoCreateJson.png) 4. Open the file `launch.json` and add the following code - ```Go Code - "env": { - "CGO_LDFLAGS": "./libdbcapiHDB.dylib" - } - ``` + ```Go Code + "env": { + "CGO_LDFLAGS": "./libdbcapiHDB.dylib" + } + ``` - ![Go Json File](GoJsonFile.png) + ![Go JSON file](GoJsonFile.png) Change `./libdbcapiHDB.dylib` to the correct file for your operating system: use `libdbcapiHDB.dylib` on macOS, `libdbcapiHDB.dll` on Windows, or `libdbcapiHDB.so` on Linux. Also ensure the dbcapi file has been copied or moved into this folder. 5. Place a breakpoint. - ![SetBreakpoint](SetGoBreakpoint.png) + ![Set a breakpoint](SetGoBreakpoint.png) 6. Select **Run | Start Debugging**. @@ -283,7 +330,8 @@ Visual Studio Code provides plugins for Go and can be used to debug an applicati ![Breakpoint](GoBreakpoint.png) - >Debugging can also be performed from the command line using [Delve](https://github.com/go-delve/delve). + > [!NOTE] + > Debugging can also be performed from the command line using [Delve](https://github.com/go-delve/delve). ### Knowledge check diff --git a/tutorials/hana-clients-hdbsql/hana-clients-hdbsql.md b/tutorials/hana-clients-hdbsql/hana-clients-hdbsql.md index 354b0595b..937b52ff6 100644 --- a/tutorials/hana-clients-hdbsql/hana-clients-hdbsql.md +++ b/tutorials/hana-clients-hdbsql/hana-clients-hdbsql.md @@ -4,7 +4,7 @@ author_name: Dan van Leeuwen author_profile: https://github.com/danielva auto_validation: true time: 15 -tags: [ tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana, programming-tool>sql] +tags: [tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana, programming-tool>sql] primary_tag: software-product>sap-hana-cloud --- @@ -33,9 +33,9 @@ This step demonstrates how to connect to a SAP HANA instance using [HDBSQL](http 1. Copy and paste the following command to see the command line options and press the space bar to advance though the information. - ```Shell - hdbsql -h | more - ``` + ```Shell + hdbsql -h | more + ``` 2. Connect to either SAP HANA Cloud or SAP HANA on-premise instance using host, port, and credentials. Details on where to find these values are covered in the third and fifth steps of the [first tutorial](hana-clients-choose-hana-instance) in this mission. @@ -75,7 +75,7 @@ This step demonstrates how to connect to a SAP HANA instance using [HDBSQL](http - The HANA Cloud instance can be configured to enable applications running from outside the SAP BTP to connect. The current setting is shown in SAP HANA Cloud Central in the screenshot below. - ![screenshot showing the allowlist](allowlist.png) + ![Allowlist in SAP HANA Cloud](allowlist.png) An example of configuring this setting is shown in [Allow connections to SAP HANA Cloud instance from selected IP addresses — using the command line](https://blogs.sap.com/2020/10/30/allow-connections-to-sap-hana-cloud-instance-from-selected-ip-addresses-using-the-command-line/). @@ -83,7 +83,9 @@ This step demonstrates how to connect to a SAP HANA instance using [HDBSQL](http - Connections to a HANA Cloud instance must use encryption. The default encryption library on Windows is mscrypto and on Linux and macOS it is OpenSSL. The following example demonstrates how one could use the SAP provided conmmoncrypto library instead of the default encryption library. Note, the following steps require that the SAP HANA Client be downloaded from the SAP Software Downloads as the download includes the SAP Common Crypto library (libsapcrypto). Note that the environment variables can also be set by running source hdbclienv.sh or hdbclienv.bat. - ```Shell (Linux or Mac) + [OPTION BEGIN [Mac and Linux]] + + ```Shell mkdir ~/.ssl # Download the public root certificate used by HANA Cloud wget --no-check-certificate https://cacerts.digicert.com/DigiCertGlobalRootCA.crt.pem -O ~/.ssl/DigiCertGlobalRootCA.crt.pem @@ -94,12 +96,12 @@ This step demonstrates how to connect to a SAP HANA instance using [HDBSQL](http export LD_LIBRARY_PATH=~/sap/hdbclient:$LD_LIBRARY_PATH # macOS only export DYLD_LIBRARY_PATH=~/sap/hdbclient - # Create a PSE (Personal Security Environment) which will be used to contain the public root certificate of SAP HANA Cloud. + # Create a PSE (Personal Security Environment) which will be used to contain the public root certificate of SAP HANA Cloud. # Press enter twice to not provide a pin sapgenpse gen_verify_pse -p "$SECUDIR/sapcli.pse" ``` - ```Shell (Linux or Mac) + ```Shell # Add the certificate to the PSE sapgenpse maintain_pk -p "$SECUDIR/sapcli.pse" -a ~/.ssl/DigiCertGlobalRootCA.crt.pem # View the contents of the PSE @@ -108,19 +110,23 @@ This step demonstrates how to connect to a SAP HANA instance using [HDBSQL](http hdbsql -sslprovider commoncrypto -n 3b2gf55e-4214-4bd9-adfc-f547d8e2d384.hana.trial-us10.hanacloud.ondemand.com:443 -u -p ``` - ```Shell (Windows) + [OPTION END] + + [OPTION BEGIN [Windows]] + + ```Shell REM In a browser download https://cacerts.digicert.com/DigiCertGlobalRootCA.crt.pem REM Show the command help for the sapgenpse sapgenpse -h REM SECDIR environment variable is required when using the commoncrypto library set SECUDIR=C:\SAP\hdbclient - REM Create a PSE (Personal Security Environment) which will be used to contain the public root certificate of SAP HANA Cloud. + REM Create a PSE (Personal Security Environment) which will be used to contain the public root certificate of SAP HANA Cloud. REM Press enter twice to not provide a pin sapgenpse gen_verify_pse -p "%SECUDIR%/sapcli.pse" REM if the above command fails, try using the -log option for additional output. ``` - ```Shell (Windows) + ```Shell REM Add the certificate to the PSE sapgenpse maintain_pk -p "%SECUDIR%/sapcli.pse" -a %USERPROFILE%/Downloads/DigiCertGlobalRootCA.crt.pem REM View the contents of the PSE @@ -129,6 +135,8 @@ This step demonstrates how to connect to a SAP HANA instance using [HDBSQL](http hdbsql -sslprovider commoncrypto -n 3b2gf55e-4214-4bd9-adfc-f547d8e2d384.hana.trial-us10.hanacloud.ondemand.com:443 -u -p ``` + [OPTION END] + For additional details see [Server Certificate Authentication](https://help.sap.com/docs/SAP_HANA_CLIENT/f1b440ded6144a54ada97ff95dac7adf/a95754380f4c4c05b728524f9cd652e3.html). - If you are on a Linux or Mac machine and the hdbsql connection fails with the error message below, it indicates that the OpenSSL library could not locate a trust store in the default location. @@ -151,7 +159,7 @@ This step demonstrates how to connect to a SAP HANA instance using [HDBSQL](http Notice that for the on-premise instance, the version number is 2.x. - ![Connect to HXE](Connect-to-host-server.png) + ![Connect to an on-premise SAP HANA](Connect-to-host-server.png) ### Create user and schema @@ -159,44 +167,48 @@ This step creates two users and a schema. `USER1` will be the owner of the tabl On Linux or a Mac, turn off page by page scroll output. Also, consult the `-j` `hdbsql` option. This enables multiple commands to be pasted at one time and does not require each result to be exited by pressing q. -```HDBSQL (Linux or Mac) +[OPTION BEGIN [Mac and Linux]] + +```HDBSQL \pa off ``` +[OPTION END] + 1. Create `USER1`. Select the command below based on the version of SAP HANA being used. Note that the message _'0 rows affected'_ means that query was successful. - ```SQL - CREATE USER USER1 PASSWORD Password1 no force_first_password_change; - CREATE USER USER2 PASSWORD Password2 no force_first_password_change; --Used in the Node.js connection pool example and the entity framework tutorial. - ``` + ```SQL + CREATE USER USER1 PASSWORD Password1 no force_first_password_change; + CREATE USER USER2 PASSWORD Password2 no force_first_password_change; --Used in the Node.js connection pool example and the entity framework tutorial. + ``` - >The end of this tutorial contains SQL statements to delete the user, schema and objects created. This may be helpful if you wish to recreate the sample dataset used in this tutorial. + > [!NOTE] + > The end of this tutorial contains SQL statements to delete the user, schema and objects created. This may be helpful if you wish to recreate the sample dataset used in this tutorial. To verify that the user was created, enter the following command. - ```SQL - SELECT USER_NAME FROM USERS; - ``` + ```SQL + SELECT USER_NAME FROM USERS; + ``` Also notice that a schema with the same name is created for this user. - ```SQL - SELECT SCHEMA_NAME FROM SCHEMAS; - ``` + ```SQL + SELECT SCHEMA_NAME FROM SCHEMAS; + ``` 2. Enable `USER1` the ability to create schema, connect as `USER1`, create a schema, and set it as the current schema. - ```SQL - SELECT CURRENT_USER, CURRENT_SCHEMA FROM DUMMY; - GRANT CREATE SCHEMA TO USER1; - CONNECT USER1 PASSWORD Password1; - CREATE SCHEMA HOTELS; - SET SCHEMA HOTELS; - GRANT SELECT ON SCHEMA HOTELS TO USER2; - GRANT SELECT ON SCHEMA HOTELS TO DBADMIN; - SELECT CURRENT_USER, CURRENT_SCHEMA FROM DUMMY; - - ``` + ```SQL + SELECT CURRENT_USER, CURRENT_SCHEMA FROM DUMMY; + GRANT CREATE SCHEMA TO USER1; + CONNECT USER1 PASSWORD Password1; + CREATE SCHEMA HOTELS; + SET SCHEMA HOTELS; + GRANT SELECT ON SCHEMA HOTELS TO USER2; + GRANT SELECT ON SCHEMA HOTELS TO DBADMIN; + SELECT CURRENT_USER, CURRENT_SCHEMA FROM DUMMY; + ``` Notice that the current user and schema have also changed from `DBADMIN` or `SYSTEM` to `USER1` and that the schema is now HOTELS. @@ -209,29 +221,30 @@ Remembering and entering IP addresses, ports, user IDs and passwords can be diff 1. Exit out of `hdbsql` and type `hdbuserstore` to see a list of available commands such as Set, List and Delete. - ```Shell - \q - hdbuserstore - ``` + ```Shell + \q + hdbuserstore + ``` `hdbuserstore` is included with the install of the SAP HANA client. 2. Using `hdbuserstore`, specify a key named `USER1UserKey` that has the host, port and credentials. Details on where to find these values are covered in the third and fifth steps of the [first tutorial](hana-clients-choose-hana-instance) in this mission. - ```Shell - hdbuserstore Set USER1UserKey : USER1 Password1 - hdbuserstore List - ``` + ```Shell + hdbuserstore Set USER1UserKey : USER1 Password1 + hdbuserstore List + ``` 3. Connect with `USER1` as the username. - ```Shell - hdbsql -U USER1UserKey - ``` + ```Shell + hdbsql -U USER1UserKey + ``` - > Uppercase U is for specifying a key from the user store, lower case u is for user. + > [!TIP] + > Uppercase `-U` is for specifying a key from the user store, lower case `-u` is for user. - >--- +--- [Using Stored Connection Information](https://help.sap.com/docs/SAP_HANA_CLIENT/f1b440ded6144a54ada97ff95dac7adf/708e5fe0e44a4764a1b6b5ea549b88f4.html) contains details on how an application can use a `hdbuserstore` key. @@ -241,296 +254,315 @@ Remembering and entering IP addresses, ports, user IDs and passwords can be diff 2. Create a folder for the exercises in this tutorial, enter that directory, and begin editing a file named `hotel.sql`. - ```Shell (Microsoft Windows) - mkdir %HOMEPATH%\HANAClientsTutorial\sql - cd %HOMEPATH%\HANAClientsTutorial\sql - notepad hotel.sql - ``` + [OPTION BEGIN [Windows]] - Substitute `pico` below for your preferred text editor. + ```Shell + mkdir %HOMEPATH%\HANAClientsTutorial\sql + cd %HOMEPATH%\HANAClientsTutorial\sql + notepad hotel.sql + ``` - ```Shell (Linux or Mac) - mkdir -p $HOME/HANAClientsTutorial/sql - cd $HOME/HANAClientsTutorial/sql - pico hotel.sql - ``` + [OPTION END] + + Substitute `pico` below for your preferred text editor. + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + mkdir -p $HOME/HANAClientsTutorial/sql + cd $HOME/HANAClientsTutorial/sql + pico hotel.sql + ``` + + [OPTION END] 3. Copy the following SQL into the file `hotel.sql`. - ```SQL - --CONNECT USER1 PASSWORD Password1; - SET SCHEMA HOTELS; - CREATE COLUMN TABLE HOTEL( - hno INTEGER PRIMARY KEY, - name NVARCHAR(50) NOT NULL, - address NVARCHAR(40) NOT NULL, - city NVARCHAR(30) NOT NULL, - state NVARCHAR(2) NOT NULL, - zip NVARCHAR(6) - ); - CREATE COLUMN TABLE ROOM( - hno INTEGER, - type NVARCHAR(6), - free NUMERIC(3), - price NUMERIC(6, 2), - PRIMARY KEY (hno, type), - FOREIGN KEY (hno) REFERENCES HOTEL - ); - CREATE COLUMN TABLE CUSTOMER( - cno INTEGER PRIMARY KEY, - title NVARCHAR(7), - firstname NVARCHAR(20), - name NVARCHAR(40) NOT NULL, - address NVARCHAR(40) NOT NULL, - zip NVARCHAR(6) - ); - CREATE COLUMN TABLE RESERVATION( - resno INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY, - rno INTEGER NOT NULL, - cno INTEGER, - hno INTEGER, - type NVARCHAR(6), - arrival DATE NOT NULL, - departure DATE NOT NULL, - PRIMARY KEY ( - "RESNO", "ARRIVAL" - ), - FOREIGN KEY(hno) REFERENCES HOTEL, - FOREIGN KEY(cno) REFERENCES CUSTOMER - ); - CREATE COLUMN TABLE MAINTENANCE( - mno INTEGER PRIMARY KEY, - hno INTEGER, - description NVARCHAR(100), - date_performed DATE, - performed_by NVARCHAR(40) - ); - - CREATE OR REPLACE PROCEDURE SHOW_RESERVATIONS( - IN IN_HNO INTEGER, IN IN_ARRIVAL DATE) - SQL SECURITY INVOKER - READS SQL DATA - AS BEGIN - SELECT - R.RESNO, - R.ARRIVAL, - DAYS_BETWEEN (R.ARRIVAL, R.DEPARTURE) as "Nights", - H.NAME, - CUS.TITLE, - CUS.FIRSTNAME AS "FIRST NAME", - CUS.NAME AS "LAST NAME" - FROM - RESERVATION AS R - LEFT OUTER JOIN - HOTEL AS H - ON H.HNO = R.HNO - LEFT OUTER JOIN - CUSTOMER AS CUS - ON CUS.CNO = R.CNO - WHERE R.ARRIVAL = :IN_ARRIVAL AND - H.HNO = :IN_HNO - ORDER BY - H.NAME ASC, - R.ARRIVAL DESC; - END; - - INSERT INTO HOTEL VALUES(10, 'Congress', '155 Beechwood St.', 'Seattle', 'WA', '20005'); - INSERT INTO HOTEL VALUES(11, 'Regency', '477 17th Avenue', 'Seattle', 'WA', '20037'); - INSERT INTO HOTEL VALUES(12, 'Long Island', '1499 Grove Street', 'Long Island', 'NY', '11788'); - INSERT INTO HOTEL VALUES(13, 'Empire State', '65 Yellowstone Dr.', 'Albany', 'NY', '12203'); - INSERT INTO HOTEL VALUES(14, 'Midtown', '12 Barnard St.', 'New York', 'NY', '10019'); - INSERT INTO HOTEL VALUES(15, 'Eighth Avenue', '112 8th Avenue', 'New York', 'NY', '10019'); - INSERT INTO HOTEL VALUES(16, 'Lake Michigan', '354 OAK Terrace', 'Chicago', 'IL', '60601'); - INSERT INTO HOTEL VALUES(17, 'Airport', '650 C Parkway', 'Rosemont', 'IL', '60018'); - INSERT INTO HOTEL VALUES(18, 'Sunshine', '200 Yellowstone Dr.', 'Clearwater', 'FL', '33575'); - INSERT INTO HOTEL VALUES(19, 'Beach', '1980 34th St.', 'Daytona Beach', 'FL', '32018'); - INSERT INTO HOTEL VALUES(20, 'Atlantic', '111 78th St.', 'Deerfield Beach', 'FL', '33441'); - INSERT INTO HOTEL VALUES(21, 'Long Beach', '35 Broadway', 'Long Beach', 'CA', '90804'); - INSERT INTO HOTEL VALUES(22, 'Indian Horse', '16 MAIN STREET', 'Palm Springs', 'CA', '92262'); - INSERT INTO HOTEL VALUES(23, 'Star', '13 Beechwood Place', 'Hollywood', 'CA', '90029'); - INSERT INTO HOTEL VALUES(24, 'River Boat', '788 MAIN STREET', 'New Orleans', 'LA', '70112'); - INSERT INTO HOTEL VALUES(25, 'Ocean Star', '45 Pacific Avenue', 'Atlantic City', 'NJ', '08401'); - INSERT INTO HOTEL VALUES(26, 'Bella Ciente', '1407 Marshall Ave', 'Longview', 'TX', '75601'); - - INSERT INTO ROOM VALUES(10, 'single', 20, 135.00); - INSERT INTO ROOM VALUES(10, 'double', 45, 200.00); - INSERT INTO ROOM VALUES(12, 'single', 10, 70.00); - INSERT INTO ROOM VALUES(12, 'double', 13, 100.00); - INSERT INTO ROOM VALUES(13, 'single', 12, 45.00); - INSERT INTO ROOM VALUES(13, 'double', 15, 80.00); - INSERT INTO ROOM VALUES(14, 'single', 20, 85.00); - INSERT INTO ROOM VALUES(14, 'double', 35, 140.00); - INSERT INTO ROOM VALUES(15, 'single', 50, 105.00); - INSERT INTO ROOM VALUES(15, 'double', 230, 180.00); - INSERT INTO ROOM VALUES(15, 'suite', 12, 500.00); - INSERT INTO ROOM VALUES(16, 'single', 10, 120.00); - INSERT INTO ROOM VALUES(16, 'double', 39, 200.00); - INSERT INTO ROOM VALUES(16, 'suite', 20, 500.00); - INSERT INTO ROOM VALUES(17, 'single', 4, 115.00); - INSERT INTO ROOM VALUES(17, 'double', 11, 180.00); - INSERT INTO ROOM VALUES(18, 'single', 15, 90.00); - INSERT INTO ROOM VALUES(18, 'double', 19, 150.00); - INSERT INTO ROOM VALUES(18, 'suite', 5, 400.00); - INSERT INTO ROOM VALUES(19, 'single', 45, 90.00); - INSERT INTO ROOM VALUES(19, 'double', 145, 150.00); - INSERT INTO ROOM VALUES(19, 'suite', 60, 300.00); - INSERT INTO ROOM VALUES(20, 'single', 11, 60.00); - INSERT INTO ROOM VALUES(20, 'double', 24, 100.00); - INSERT INTO ROOM VALUES(21, 'single', 2, 70.00); - INSERT INTO ROOM VALUES(21, 'double', 10, 130.00); - INSERT INTO ROOM VALUES(22, 'single', 34, 80.00); - INSERT INTO ROOM VALUES(22, 'double', 78, 140.00); - INSERT INTO ROOM VALUES(22, 'suite', 55, 350.00); - INSERT INTO ROOM VALUES(23, 'single', 89, 160.00); - INSERT INTO ROOM VALUES(23, 'double', 300, 270.00); - INSERT INTO ROOM VALUES(23, 'suite', 100, 700.00); - INSERT INTO ROOM VALUES(24, 'single', 10, 125.00); - INSERT INTO ROOM VALUES(24, 'double', 9, 200.00); - INSERT INTO ROOM VALUES(24, 'suite', 78, 600.00); - INSERT INTO ROOM VALUES(25, 'single', 44, 100.00); - INSERT INTO ROOM VALUES(25, 'double', 115, 190.00); - INSERT INTO ROOM VALUES(25, 'suite', 6, 450.00); - - INSERT INTO CUSTOMER VALUES(1000, 'Mrs', 'Jenny', 'Porter', '1340 N. Ash Street, #3', '10580'); - INSERT INTO CUSTOMER VALUES(1001, 'Mr', 'Peter', 'Brown', '1001 34th St., APT.3', '48226'); - INSERT INTO CUSTOMER VALUES(1002, 'Company', NULL, 'Datasoft', '486 Maple St.', '90018'); - INSERT INTO CUSTOMER VALUES(1003, 'Mrs', 'Rose', 'Brian', '500 Yellowstone Drive, #2', '75243'); - INSERT INTO CUSTOMER VALUES(1004, 'Mrs', 'Mary', 'Griffith', '3401 Elder Lane', '20005'); - INSERT INTO CUSTOMER VALUES(1005, 'Mr', 'Martin', 'Randolph', '340 MAIN STREET, #7', '60615'); - INSERT INTO CUSTOMER VALUES(1006, 'Mrs', 'Sally', 'Smith', '250 Curtis Street', '75243'); - INSERT INTO CUSTOMER VALUES(1007, 'Mr', 'Mike', 'Jackson', '133 BROADWAY APT. 1', '45211'); - INSERT INTO CUSTOMER VALUES(1008, 'Mrs', 'Rita', 'Doe', '2000 Humboldt St., #6', '97213'); - INSERT INTO CUSTOMER VALUES(1009, 'Mr', 'George', 'Howe', '111 B Parkway, #23', '75243'); - INSERT INTO CUSTOMER VALUES(1010, 'Mr', 'Frank', 'Miller', '27 5th St., 76', '95054'); - INSERT INTO CUSTOMER VALUES(1011, 'Mrs', 'Susan', 'Baker', '200 MAIN STREET, #94', '90018'); - INSERT INTO CUSTOMER VALUES(1012, 'Mr', 'Joseph', 'Peters', '700 S. Ash St., APT.12', '92714'); - INSERT INTO CUSTOMER VALUES(1013, 'Company', NULL, 'TOOLware', '410 Mariposa St., #10', '20019'); - INSERT INTO CUSTOMER VALUES(1014, 'Mr', 'Antony', 'Jenkins', '55 A Parkway, #15', '20903'); - INSERT INTO RESERVATION VALUES(1, 100, 1000, 11, 'single', '2020-12-24', '2020-12-27'); - INSERT INTO RESERVATION VALUES(2, 110, 1001, 11, 'double', '2020-12-24', '2021-01-03'); - INSERT INTO RESERVATION VALUES(3, 120, 1002, 15, 'suite', '2020-11-14', '2020-11-18'); - INSERT INTO RESERVATION VALUES(4, 130, 1009, 21, 'single', '2019-02-01', '2019-02-03'); - INSERT INTO RESERVATION VALUES(5, 150, 1006, 17, 'double', '2019-03-14', '2019-03-24'); - INSERT INTO RESERVATION VALUES(6, 140, 1013, 20, 'double', '2020-04-12', '2020-04-30'); - INSERT INTO RESERVATION VALUES(7, 160, 1011, 17, 'single', '2020-04-12', '2020-04-15'); - INSERT INTO RESERVATION VALUES(8, 170, 1014, 25, 'suite', '2020-09-01', '2020-09-03'); - INSERT INTO RESERVATION VALUES(9, 180, 1001, 22, 'double', '2020-12-23', '2021-01-08'); - INSERT INTO RESERVATION VALUES(10, 190, 1013, 24, 'double', '2020-11-14', '2020-11-17'); - - INSERT INTO MAINTENANCE VALUES(10, 24, 'Replace pool liner and pump', '2019-03-21', 'Discount Pool Supplies'); - INSERT INTO MAINTENANCE VALUES(11, 25, 'Renovate the bar area. Replace TV and speakers', '2020-11-29', 'TV and Audio Superstore'); - INSERT INTO MAINTENANCE VALUES(12, 26, 'Roof repair due to storm', null, null); - - SELECT SCHEMA_NAME, OBJECT_NAME, OBJECT_TYPE, OWNER_NAME FROM "PUBLIC"."OWNERSHIP" WHERE OWNER_NAME = 'USER1'; - ``` + ```SQL + --CONNECT USER1 PASSWORD Password1; + SET SCHEMA HOTELS; + CREATE COLUMN TABLE HOTEL( + hno INTEGER PRIMARY KEY, + name NVARCHAR(50) NOT NULL, + address NVARCHAR(40) NOT NULL, + city NVARCHAR(30) NOT NULL, + state NVARCHAR(2) NOT NULL, + zip NVARCHAR(6) + ); + CREATE COLUMN TABLE ROOM( + hno INTEGER, + type NVARCHAR(6), + free NUMERIC(3), + price NUMERIC(6, 2), + PRIMARY KEY (hno, type), + FOREIGN KEY (hno) REFERENCES HOTEL + ); + CREATE COLUMN TABLE CUSTOMER( + cno INTEGER PRIMARY KEY, + title NVARCHAR(7), + firstname NVARCHAR(20), + name NVARCHAR(40) NOT NULL, + address NVARCHAR(40) NOT NULL, + zip NVARCHAR(6) + ); + CREATE COLUMN TABLE RESERVATION( + resno INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY, + rno INTEGER NOT NULL, + cno INTEGER, + hno INTEGER, + type NVARCHAR(6), + arrival DATE NOT NULL, + departure DATE NOT NULL, + PRIMARY KEY ( + "RESNO", "ARRIVAL" + ), + FOREIGN KEY(hno) REFERENCES HOTEL, + FOREIGN KEY(cno) REFERENCES CUSTOMER + ); + CREATE COLUMN TABLE MAINTENANCE( + mno INTEGER PRIMARY KEY, + hno INTEGER, + description NVARCHAR(100), + date_performed DATE, + performed_by NVARCHAR(40) + ); + + CREATE OR REPLACE PROCEDURE SHOW_RESERVATIONS( + IN IN_HNO INTEGER, IN IN_ARRIVAL DATE) + SQL SECURITY INVOKER + READS SQL DATA + AS BEGIN + SELECT + R.RESNO, + R.ARRIVAL, + DAYS_BETWEEN (R.ARRIVAL, R.DEPARTURE) as "Nights", + H.NAME, + CUS.TITLE, + CUS.FIRSTNAME AS "FIRST NAME", + CUS.NAME AS "LAST NAME" + FROM + RESERVATION AS R + LEFT OUTER JOIN + HOTEL AS H + ON H.HNO = R.HNO + LEFT OUTER JOIN + CUSTOMER AS CUS + ON CUS.CNO = R.CNO + WHERE R.ARRIVAL = :IN_ARRIVAL AND + H.HNO = :IN_HNO + ORDER BY + H.NAME ASC, + R.ARRIVAL DESC; + END; + + INSERT INTO HOTEL VALUES(10, 'Congress', '155 Beechwood St.', 'Seattle', 'WA', '20005'); + INSERT INTO HOTEL VALUES(11, 'Regency', '477 17th Avenue', 'Seattle', 'WA', '20037'); + INSERT INTO HOTEL VALUES(12, 'Long Island', '1499 Grove Street', 'Long Island', 'NY', '11788'); + INSERT INTO HOTEL VALUES(13, 'Empire State', '65 Yellowstone Dr.', 'Albany', 'NY', '12203'); + INSERT INTO HOTEL VALUES(14, 'Midtown', '12 Barnard St.', 'New York', 'NY', '10019'); + INSERT INTO HOTEL VALUES(15, 'Eighth Avenue', '112 8th Avenue', 'New York', 'NY', '10019'); + INSERT INTO HOTEL VALUES(16, 'Lake Michigan', '354 OAK Terrace', 'Chicago', 'IL', '60601'); + INSERT INTO HOTEL VALUES(17, 'Airport', '650 C Parkway', 'Rosemont', 'IL', '60018'); + INSERT INTO HOTEL VALUES(18, 'Sunshine', '200 Yellowstone Dr.', 'Clearwater', 'FL', '33575'); + INSERT INTO HOTEL VALUES(19, 'Beach', '1980 34th St.', 'Daytona Beach', 'FL', '32018'); + INSERT INTO HOTEL VALUES(20, 'Atlantic', '111 78th St.', 'Deerfield Beach', 'FL', '33441'); + INSERT INTO HOTEL VALUES(21, 'Long Beach', '35 Broadway', 'Long Beach', 'CA', '90804'); + INSERT INTO HOTEL VALUES(22, 'Indian Horse', '16 MAIN STREET', 'Palm Springs', 'CA', '92262'); + INSERT INTO HOTEL VALUES(23, 'Star', '13 Beechwood Place', 'Hollywood', 'CA', '90029'); + INSERT INTO HOTEL VALUES(24, 'River Boat', '788 MAIN STREET', 'New Orleans', 'LA', '70112'); + INSERT INTO HOTEL VALUES(25, 'Ocean Star', '45 Pacific Avenue', 'Atlantic City', 'NJ', '08401'); + INSERT INTO HOTEL VALUES(26, 'Bella Ciente', '1407 Marshall Ave', 'Longview', 'TX', '75601'); + + INSERT INTO ROOM VALUES(10, 'single', 20, 135.00); + INSERT INTO ROOM VALUES(10, 'double', 45, 200.00); + INSERT INTO ROOM VALUES(12, 'single', 10, 70.00); + INSERT INTO ROOM VALUES(12, 'double', 13, 100.00); + INSERT INTO ROOM VALUES(13, 'single', 12, 45.00); + INSERT INTO ROOM VALUES(13, 'double', 15, 80.00); + INSERT INTO ROOM VALUES(14, 'single', 20, 85.00); + INSERT INTO ROOM VALUES(14, 'double', 35, 140.00); + INSERT INTO ROOM VALUES(15, 'single', 50, 105.00); + INSERT INTO ROOM VALUES(15, 'double', 230, 180.00); + INSERT INTO ROOM VALUES(15, 'suite', 12, 500.00); + INSERT INTO ROOM VALUES(16, 'single', 10, 120.00); + INSERT INTO ROOM VALUES(16, 'double', 39, 200.00); + INSERT INTO ROOM VALUES(16, 'suite', 20, 500.00); + INSERT INTO ROOM VALUES(17, 'single', 4, 115.00); + INSERT INTO ROOM VALUES(17, 'double', 11, 180.00); + INSERT INTO ROOM VALUES(18, 'single', 15, 90.00); + INSERT INTO ROOM VALUES(18, 'double', 19, 150.00); + INSERT INTO ROOM VALUES(18, 'suite', 5, 400.00); + INSERT INTO ROOM VALUES(19, 'single', 45, 90.00); + INSERT INTO ROOM VALUES(19, 'double', 145, 150.00); + INSERT INTO ROOM VALUES(19, 'suite', 60, 300.00); + INSERT INTO ROOM VALUES(20, 'single', 11, 60.00); + INSERT INTO ROOM VALUES(20, 'double', 24, 100.00); + INSERT INTO ROOM VALUES(21, 'single', 2, 70.00); + INSERT INTO ROOM VALUES(21, 'double', 10, 130.00); + INSERT INTO ROOM VALUES(22, 'single', 34, 80.00); + INSERT INTO ROOM VALUES(22, 'double', 78, 140.00); + INSERT INTO ROOM VALUES(22, 'suite', 55, 350.00); + INSERT INTO ROOM VALUES(23, 'single', 89, 160.00); + INSERT INTO ROOM VALUES(23, 'double', 300, 270.00); + INSERT INTO ROOM VALUES(23, 'suite', 100, 700.00); + INSERT INTO ROOM VALUES(24, 'single', 10, 125.00); + INSERT INTO ROOM VALUES(24, 'double', 9, 200.00); + INSERT INTO ROOM VALUES(24, 'suite', 78, 600.00); + INSERT INTO ROOM VALUES(25, 'single', 44, 100.00); + INSERT INTO ROOM VALUES(25, 'double', 115, 190.00); + INSERT INTO ROOM VALUES(25, 'suite', 6, 450.00); + + INSERT INTO CUSTOMER VALUES(1000, 'Mrs', 'Jenny', 'Porter', '1340 N. Ash Street, #3', '10580'); + INSERT INTO CUSTOMER VALUES(1001, 'Mr', 'Peter', 'Brown', '1001 34th St., APT.3', '48226'); + INSERT INTO CUSTOMER VALUES(1002, 'Company', NULL, 'Datasoft', '486 Maple St.', '90018'); + INSERT INTO CUSTOMER VALUES(1003, 'Mrs', 'Rose', 'Brian', '500 Yellowstone Drive, #2', '75243'); + INSERT INTO CUSTOMER VALUES(1004, 'Mrs', 'Mary', 'Griffith', '3401 Elder Lane', '20005'); + INSERT INTO CUSTOMER VALUES(1005, 'Mr', 'Martin', 'Randolph', '340 MAIN STREET, #7', '60615'); + INSERT INTO CUSTOMER VALUES(1006, 'Mrs', 'Sally', 'Smith', '250 Curtis Street', '75243'); + INSERT INTO CUSTOMER VALUES(1007, 'Mr', 'Mike', 'Jackson', '133 BROADWAY APT. 1', '45211'); + INSERT INTO CUSTOMER VALUES(1008, 'Mrs', 'Rita', 'Doe', '2000 Humboldt St., #6', '97213'); + INSERT INTO CUSTOMER VALUES(1009, 'Mr', 'George', 'Howe', '111 B Parkway, #23', '75243'); + INSERT INTO CUSTOMER VALUES(1010, 'Mr', 'Frank', 'Miller', '27 5th St., 76', '95054'); + INSERT INTO CUSTOMER VALUES(1011, 'Mrs', 'Susan', 'Baker', '200 MAIN STREET, #94', '90018'); + INSERT INTO CUSTOMER VALUES(1012, 'Mr', 'Joseph', 'Peters', '700 S. Ash St., APT.12', '92714'); + INSERT INTO CUSTOMER VALUES(1013, 'Company', NULL, 'TOOLware', '410 Mariposa St., #10', '20019'); + INSERT INTO CUSTOMER VALUES(1014, 'Mr', 'Antony', 'Jenkins', '55 A Parkway, #15', '20903'); + INSERT INTO RESERVATION VALUES(1, 100, 1000, 11, 'single', '2020-12-24', '2020-12-27'); + INSERT INTO RESERVATION VALUES(2, 110, 1001, 11, 'double', '2020-12-24', '2021-01-03'); + INSERT INTO RESERVATION VALUES(3, 120, 1002, 15, 'suite', '2020-11-14', '2020-11-18'); + INSERT INTO RESERVATION VALUES(4, 130, 1009, 21, 'single', '2019-02-01', '2019-02-03'); + INSERT INTO RESERVATION VALUES(5, 150, 1006, 17, 'double', '2019-03-14', '2019-03-24'); + INSERT INTO RESERVATION VALUES(6, 140, 1013, 20, 'double', '2020-04-12', '2020-04-30'); + INSERT INTO RESERVATION VALUES(7, 160, 1011, 17, 'single', '2020-04-12', '2020-04-15'); + INSERT INTO RESERVATION VALUES(8, 170, 1014, 25, 'suite', '2020-09-01', '2020-09-03'); + INSERT INTO RESERVATION VALUES(9, 180, 1001, 22, 'double', '2020-12-23', '2021-01-08'); + INSERT INTO RESERVATION VALUES(10, 190, 1013, 24, 'double', '2020-11-14', '2020-11-17'); + + INSERT INTO MAINTENANCE VALUES(10, 24, 'Replace pool liner and pump', '2019-03-21', 'Discount Pool Supplies'); + INSERT INTO MAINTENANCE VALUES(11, 25, 'Renovate the bar area. Replace TV and speakers', '2020-11-29', 'TV and Audio Superstore'); + INSERT INTO MAINTENANCE VALUES(12, 26, 'Roof repair due to storm', null, null); + + SELECT SCHEMA_NAME, OBJECT_NAME, OBJECT_TYPE, OWNER_NAME FROM "PUBLIC"."OWNERSHIP" WHERE OWNER_NAME = 'USER1'; + ``` 4. Execute the SQL with the command below. This is an example of running commands in non-interactive mode. - ```Shell - hdbsql -U USER1UserKey -I hotel.sql - ``` + ```Shell + hdbsql -U USER1UserKey -I hotel.sql + ``` Confirm that 15 records have been inserted. - ```Shell - hdbsql -U USER1UserKey "SELECT COUNT(*) FROM HOTELS.CUSTOMER"; - ``` + ```Shell + hdbsql -U USER1UserKey "SELECT COUNT(*) FROM HOTELS.CUSTOMER"; + ``` - ![result](select.png) + ![hdbsql query result](select.png) View the list of created objects. - ```SQL - hdbsql -U USER1UserKey - \dt HOTELS. - \dp HOTELS. - ``` + ```SQL + hdbsql -U USER1UserKey + \dt HOTELS. + \dp HOTELS. + ``` - ![View the list of tables and procedures](list-tables-procs.png) + ![View the list of tables and procedures](list-tables-procs.png) - If the output is not aligned, aligned output mode can be toggled with \al in hdbsql. + > [!TIP] + > If the output is not aligned, aligned output mode can be toggled with `\al` in hdbsql. For further information, see [CREATE TABLE Statement](https://help.sap.com/docs/hana-cloud-database/sap-hana-cloud-sap-hana-database-sql-reference-guide/create-table-statement-data-definition) and [INSERT Statement](https://help.sap.com/docs/hana-cloud-database/sap-hana-cloud-sap-hana-database-sql-reference-guide/insert-statement-data-manipulation). 5. Identifiers such as table names are automatically upper cased unless they are within "". - ```SQL - SELECT * FROM HoTeLs.RoOm; --succeeds - SELECT * FROM "HoTeLs"."RoOm"; --fails - SELECT * FROM "HOTELS"."ROOM"; --succeeds - ``` + ```SQL + SELECT * FROM HoTeLs.RoOm; --succeeds + SELECT * FROM "HoTeLs"."RoOm"; --fails + SELECT * FROM "HOTELS"."ROOM"; --succeeds + ``` For further details, consult [Identifiers and case sensitivity](https://help.sap.com/docs/hana-cloud-database/sap-hana-cloud-sap-hana-database-sql-reference-guide/introduction-to-sql#loio209f5020751910148fd8fe88aa4d79d9__identifiers_case). - Should you wish to remove the contents of a table, the table itself, a schema or a user, the following statements can be executed. Do not execute these now as `USER1` and the hotel data set will be used subsequently in this tutorial. + Should you wish to remove the contents of a table, the table itself, a schema or a user, the following statements can be executed. - ```SQL - --DO NOT EXECUTE UNLESS YOU ARE FINISHED WITH THE TUTORIAL - DROP SCHEMA HOTELS CASCADE; - DROP USER USER1 CASCADE; - DROP USER USER2 CASCADE; - ``` + > [!WARNING] + > Do not execute the following statements unless you are finished with the tutorial. They permanently remove the schema, users, and sample dataset. + + ```SQL + DROP SCHEMA HOTELS CASCADE; + DROP USER USER1 CASCADE; + DROP USER USER2 CASCADE; + ``` ### Interactive, non-interactive, substitution variables, and prepared statements 1. HDBSQL can [run commands](https://help.sap.com/docs/SAP_HANA_CLIENT/f1b440ded6144a54ada97ff95dac7adf/6097e699826343d0879244185d680a0d.html) interactively, or non-interactively. A few examples are shown below. - ```SQL - SELECT * FROM HOTELS.CUSTOMER; -- interactive - hdbsql -U USER1UserKey "SELECT * FROM HOTELS.CUSTOMER"; -- non-interactive - hdbsql -U USER1UserKey -I hotel.sql -- batch file - ``` + ```SQL + SELECT * FROM HOTELS.CUSTOMER; -- interactive + hdbsql -U USER1UserKey "SELECT * FROM HOTELS.CUSTOMER"; -- non-interactive + hdbsql -U USER1UserKey -I hotel.sql -- batch file + ``` 2. [Substitution variables](https://help.sap.com/docs/SAP_HANA_CLIENT/f1b440ded6144a54ada97ff95dac7adf/18ce51f468bc4cfe9112e6be79953e93.html) can be used to pass parameters. Create a file named `findCustomers.sql`. - ```Shell (Windows) - notepad findCustomers.sql - ``` + [OPTION BEGIN [Windows]] - ```Shell (Linux or Mac) - pico findCustomers.sql - ``` + ```Shell + notepad findCustomers.sql + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + pico findCustomers.sql + ``` + + [OPTION END] Given the following SQL statement: - ```SQL (findCustomers.sql) - SELECT * FROM HOTELS.CUSTOMER WHERE FIRSTNAME LIKE '&nameParam' - ``` + ```SQL (findCustomers.sql) + SELECT * FROM HOTELS.CUSTOMER WHERE FIRSTNAME LIKE '&nameParam' + ``` We can call the query by executing the following command: - ```Shell - hdbsql -A -U USER1UserKey -V nameParam=J% -I findCustomers.sql - ``` + ```Shell + hdbsql -A -U USER1UserKey -V nameParam=J% -I findCustomers.sql + ``` - The -V option specifies a named variable that can be used within the SQL specified after the -I option. + The -V option specifies a named variable that can be used within the SQL specified after the -I option. - ![example of substitution parameters](subst.png) + ![Example of substitution parameters](subst.png) It is also possible to define new variables and list the defined variables as shown below. - ```SQL - hdbsql -A -U USER1UserKey -V nameParam=J% - \vd titleParam Mr - \vl - SELECT * FROM HOTELS.CUSTOMER WHERE TITLE = '&titleParam' AND FIRSTNAME LIKE '&nameParam' - ``` + ```SQL + hdbsql -A -U USER1UserKey -V nameParam=J% + \vd titleParam Mr + \vl + SELECT * FROM HOTELS.CUSTOMER WHERE TITLE = '&titleParam' AND FIRSTNAME LIKE '&nameParam' + ``` - ![further example of substitution parameters](subst2.png) + ![Further example of substitution parameters](subst2.png) See [SAP HANA HDBSQL Options](https://help.sap.com/docs/SAP_HANA_CLIENT/f1b440ded6144a54ada97ff95dac7adf/c24d054bbb571014b253ac5d6943b5bd.html) for details on the options to list and define substitution variables. 3. HDBSQL will prompt for required parameters. A few examples follow. - ```SQL - SELECT * FROM HOTELS.CUSTOMER WHERE FIRSTNAME LIKE ?; - ``` + ```SQL + SELECT * FROM HOTELS.CUSTOMER WHERE FIRSTNAME LIKE ?; + ``` - ```SQL - CALL HOTELS.SHOW_RESERVATIONS(?, ?); - ``` + ```SQL + CALL HOTELS.SHOW_RESERVATIONS(?, ?); + ``` ![Prompting for parameters](prepared.png) diff --git a/tutorials/hana-clients-install/hana-clients-install.md b/tutorials/hana-clients-install/hana-clients-install.md index e14862512..543025f16 100644 --- a/tutorials/hana-clients-install/hana-clients-install.md +++ b/tutorials/hana-clients-install/hana-clients-install.md @@ -4,7 +4,7 @@ author_name: Dan van Leeuwen author_profile: https://github.com/danielva auto_validation: true time: 10 -tags: [ tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana] +tags: [tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana] primary_tag: software-product>sap-hana-cloud --- @@ -23,7 +23,9 @@ primary_tag: software-product>sap-hana-cloud ## Intro -This tutorial will demonstrate how to install the SAP HANA client. The next tutorial in this mission will demonstrate how to use HDBSQL, which is a command line utility included with the client's installation, to connect to SAP HANA. The tutorials cover Microsoft Windows, Linux and Mac. If there are commands that are different depending on the platform, multiple sets of commands will be provided, and the title will say Shell (Microsoft Windows) or Shell (Linux or Mac). On Microsoft Windows, in this tutorial, the shell used is the Command Prompt. +The tutorials cover Windows, macOS, and Linux. Where commands differ by operating system, OS-conditional content is provided. The tutorial platform automatically displays the instructions that match the reader's selected operating system. + +On Windows, this tutorial uses Command Prompt commands unless otherwise noted. --- @@ -31,101 +33,126 @@ This tutorial will demonstrate how to install the SAP HANA client. The next tut The SAP HANA client provides a set of utilities and drivers to connect to and query a SAP HANA database from multiple programming APIs, such as Node.js, Python or Java as shown below. -![drivers](drivers.png) +![SAP HANA Client drivers](drivers.png) For a complete list, see [SAP HANA Client Interface Programming Reference](https://help.sap.com/docs/SAP_HANA_CLIENT/f1b440ded6144a54ada97ff95dac7adf/ce5509c492af4a9f84ee519d5659f186.html). For a list of newly added features, see [New and Changed Features in the SAP HANA Client](https://help.sap.com/docs/SAP_HANA_CLIENT/79ae9d3916b84356a89744c65793b924/22485d2937c4427fbbedefe3cc158571.html) or the [release notes](https://launchpad.support.sap.com/#/notes/2941449). -The SAP HANA client can be used to connect to different versions of SAP HANA. For example, a `2.28.x` client can connect to SAP HANA Cloud or SAP HANA 2.0. For more information, see [SAP HANA Client and SAP HANA Cloud Compatibility](https://me.sap.com/notes/3082128) and [SAP HANA client and server cross-version compatibility](https://me.sap.com/notes/0001906576). +The SAP HANA client can be used to connect to different versions of SAP HANA. For example, a `2.30.x` client can connect to SAP HANA Cloud or SAP HANA 2.0. For more information, see [SAP HANA Client and SAP HANA Cloud Compatibility](https://me.sap.com/notes/3082128) and [SAP HANA client and server cross-version compatibility](https://me.sap.com/notes/0001906576). ### Install from SAP Development Tools 1. Download the client installer for your platform (Microsoft Windows, Linux, or Mac) from the [SAP Development Tools](https://tools.hana.ondemand.com/#hanatools) website under the HANA tab and the SAP HANA Client 2.0 section. - >An alternate location to download the client installer (SAP Software Center) is described in step 3 which includes the SAP Common Crypto library and additional platforms such as Windows 32-bit and AIX. SAP Software Center also may contain newer versions and patches before they are available on the SAP Development Tools site. + > [!NOTE] + > An alternate location to download the client installer (SAP Software Center) is described in step 3 which includes the SAP Common Crypto library and additional platforms such as Windows 32-bit and AIX. SAP Software Center also may contain newer versions and patches before they are available on the SAP Development Tools site. + + ![Client download](Client-install.png) + +2. Access the contents of the downloaded install. - ![Client Download](Client-install.png) + [OPTION BEGIN [Windows and Linux]] -2. On Microsoft Windows, unzip the downloaded file in a temporary location. + ```Shell + tar -zxvf hanaclient*.tar.gz + ``` - On Linux, use the following: + [OPTION END] - ```Shell (Linux) - tar -zxvf hanaclient*.tar.gz - ``` + [OPTION BEGIN [Mac]] - On Mac, use the following: + ```Shell + hdiutil attach hanaclient-*.dmg + cd "/Volumes/SAP HANA Client" + ``` - ```Shell (Mac) - hdiutil attach hanaclient-*.dmg - cd "/Volumes/SAP HANA Client" - ``` + [OPTION END] 3. Start the graphical installer `hdbsetup` or use the command line installer `hdbinst`. - ```Shell (Microsoft Windows) - hdbsetup.exe - ``` + [OPTION BEGIN [Windows]] + + ```Shell + hdbsetup.exe + ``` + + [OPTION END] - ```Shell (Linux or Mac) - ./hdbsetup - ``` + [OPTION BEGIN [Mac and Linux]] + + ```Shell + ./hdbsetup + ``` + + [OPTION END] Set the install directory to `C:\SAP\hdbclient` on Microsoft Windows or to `users/your_user/sap/hdbclient` on Linux or macOS and complete the installation. - ![Client-install](download-client.png) + ![Client install](download-client.png) + > [!TIP] > If the install fails, try running the installer with administrator privilege (i.e. On Microsoft Windows, right-click on `hdbsetup.exe` and choose Run as an administrator). + > [!TIP] > If an older version is already installed, it can be upgraded or it can be uninstalled by running `hdbuninst` from the folder where the client is installed. For example, `c:\sap\hdbclient\install\hdbuninst` -4. After the installation process is completed, identify the environment variables that were set by the install. On Microsoft Windows, click the **Start** icon and search for **environment variables**. Press the OK button to ensure the changes made by the installer are now active in newly opened command prompts. +4. After the installation process is completed, verify that the required environment variables have been configured. + + [OPTION BEGIN [Windows]] + + Click the **Start** icon and search for **environment variables**. Press the **OK** button to ensure the changes made by the installer are active in newly opened command prompts. ![Environment variable](env-variable.png) - These variables can be seen in a command prompt using the set command as shown below. + These variables can be seen in a command prompt using the `set` command as shown below. - ![using set to view environment variables](env-variables.png) + ![Using set to view environment variables](env-variables.png) - >For details on how to configure your path on a Mac see [this](https://blogs.sap.com/2020/04/03/quick-tip-how-to-add-hdbsql-to-a-path-on-macos/) blog post and proceed to sub-step 5. - > - >To configure your path on Linux: + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + Open an editor to edit the file `.bash_profile`, `.profile`, or `.zshrc`. - >Open an editor to edit the file `.bash_profile`, `.profile`, or `.zshrc`. + ```Shell + pico ~/.bash_profile + ``` - >```Shell (Linux or Mac) - >pico ~/.bash_profile - >``` + This tutorial uses notepad and `pico` as default text editors, but any text editor will do. - >This tutorial uses notepad and `pico` as default text editors, but any text editor will do. - >`Pico` can be installed on SUSE Linux with + Add the following line to the `.bash_profile` after adjusting the path to match the location where the SAP HANA client was installed. - >```Shell (Linux SUSE) - >sudo zypper install pico - >``` + ```Shell + export PATH=$PATH:/home/dan/sap/hdbclient + ``` - >Add the following line to the .bash_profile after adjusting the path to match the location of where the SAP HANA client was installed. + Run the following command to immediately apply the changes made to the `.bash_profile` file. - >```Shell (Linux or Mac) - >export PATH=$PATH:/home/dan/sap/hdbclient - >``` + ```Shell + source ~/.bash_profile + ``` - >Run the source command to immediately apply all the changes made to the `.bash_profile` file + For details on how to configure your path on macOS see [this](https://blogs.sap.com/2020/04/03/quick-tip-how-to-add-hdbsql-to-a-path-on-macos/) blog post and proceed to step 5. - >```Shell (Linux or Mac) - >source ~/.bash_profile - >``` + [OPTION END] + + > [!TIP] + > On SUSE Linux, if `pico` is not installed, install it with: + > + > ```Shell + > sudo zypper install pico + > ``` 5. In the `hdbclient` folder, notice that files such as `hdbsql` and the client database drivers are available. - ![Clients Post Installation](Clients-post-installation.png) + ![Post installation](Clients-post-installation.png) 6. Run the following command in a newly opened shell to verify the installation succeeded and the path is correct. - ```Shell - hdbsql -v - ``` + ```Shell + hdbsql -v + ``` ![Version of HDBSQL](hdbsql-v-cmd-prompt.png) @@ -143,6 +170,7 @@ The SAP Cryptographic Library is only required when client-side data encryption Another download location is the [SAP Software Center](https://me.sap.com/softwarecenter), which requires signing in before downloading. SAP Software Center provides the very latest version of the SAP HANA client as well as additional platforms such as 32-bit Windows and AIX. Versions of the SAP HANA client downloaded from here include the SAP Common Crypto Library. +> [!NOTE] > For additional details on supported platforms, see SAP Note [3165810 - SAP HANA Client Supported Platforms](https://launchpad.support.sap.com/#/notes/3165810) and SAP Note [2938939 - SAP HANA Client Legacy Platforms](https://launchpad.support.sap.com/#/notes/2938939). 1. Select **Support Packages & Patches**, **By Alphabetical Index**, and **H**. @@ -165,18 +193,27 @@ Another download location is the [SAP Software Center](https://me.sap.com/softwa The command to extract a `.sar` file is shown below. The command options are extract, verbose and file. Make sure the `.sar` file you want to extract is in the same directory as the SAPCAR executable. - ```Shell (Microsoft Windows Command Prompt) - SAPCAR_600-70009506.EXE -xvf IMDB_CLIENT*.SAR - ``` + [OPTION BEGIN [Windows]] + + ```Shell + SAPCAR_600-70009506.EXE -xvf IMDB_CLIENT*.SAR + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + chmod u+x SAPCAR + ./SAPCAR -xvf IMDB_CLIENT*.SAR + ``` - ```Shell (Linux or Mac) - chmod u+x SAPCAR - ./SAPCAR -xvf IMDB_CLIENT*.SAR - ``` + [OPTION END] 3. Install the software as shown in sub-step 3 of Install from SAP Development Tools. - >For further information on SAPCAR or if you are having troubles using it, see [SAP HANA, SAPCAR, and macOS](https://blogs.sap.com/2020/03/18/sap-hana-sapcar-and-macos/). + > [!TIP] + > For further information on SAPCAR or if you are having troubles using it, see [SAP HANA, SAPCAR, and macOS](https://blogs.sap.com/2020/03/18/sap-hana-sapcar-and-macos/). ### Knowledge check diff --git a/tutorials/hana-clients-jdbc/hana-clients-jdbc.md b/tutorials/hana-clients-jdbc/hana-clients-jdbc.md index fbe0c9b8e..98d2d3ebf 100644 --- a/tutorials/hana-clients-jdbc/hana-clients-jdbc.md +++ b/tutorials/hana-clients-jdbc/hana-clients-jdbc.md @@ -4,7 +4,7 @@ author_name: Dan van Leeuwen author_profile: https://github.com/danielva auto_validation: true time: 15 -tags: [ tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana, programming-tool>java] +tags: [tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana, programming-tool>java] primary_tag: software-product>sap-hana-cloud --- @@ -41,26 +41,35 @@ java -version javac -version ``` -If these commands fail, ensure that the folder they are located in, is included in your path. +> [!TIP] +> If these commands fail, ensure that Java is included in your system path. + +[OPTION BEGIN [Linux]] The following command will install Java on openSUSE Leap 15.5. -```Shell (Linux) +```Shell sudo zypper install java-11-openjdk-devel ``` -On macOS, you can install Java 11 using Homebrew with the following command: +[OPTION END] + +[OPTION BEGIN [Mac]] -```Shell (Mac) +On Mac, you can install Java 11 using Homebrew with the following command: + +```Shell brew install openjdk@11 ``` To make it visible to system tools and IDEs, you may need to run the following command: -```Shell (Mac) +```Shell sudo ln -sfn /opt/homebrew/opt/openjdk@11/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-11.jdk ``` +[OPTION END] + ### Examine the SAP HANA JDBC driver The SAP HANA driver for JDBC is a [Multi-Release JAR file](https://openjdk.java.net/jeps/238) and as such supports multiple versions of Java. It is available in the client installation folder at `C:\SAP\hdbclient\ngdbc.jar` and in the maven repository at [MVN Repository - ngdbc](https://mvnrepository.com/artifact/com.sap.cloud.db.jdbc/ngdbc). @@ -69,37 +78,56 @@ The SAP HANA driver for JDBC is a [Multi-Release JAR file](https://openjdk.java. 1. Run the following command for version information. If needed, adjust the path to match the installation location on your machine. - ```Shell (Microsoft Windows) - java -jar C:\SAP\hdbclient\ngdbc.jar -v - ``` + [OPTION BEGIN [Windows]] - ```Shell (Linux or Mac) - java -jar ~/sap/hdbclient/ngdbc.jar -v - ``` + ```Shell + java -jar C:\SAP\hdbclient\ngdbc.jar -v + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + java -jar ~/sap/hdbclient/ngdbc.jar -v + ``` + + [OPTION END] 2. Run the command again without the `-v` to open the configuration window, which provides driver information and the ability to set trace information: ![JDBC-Driver-Trace-Config](JDBC-Driver-Trace-Config.png) - >The JDBC driver has a different version number than the rest of the SAP HANA client interfaces. + > [!NOTE] + > The JDBC driver has a different version number than the rest of the SAP HANA client interfaces. The trace options are further described at [JDBC Tracing and Trace Options](https://help.sap.com/docs/SAP_HANA_CLIENT/f1b440ded6144a54ada97ff95dac7adf/4033f8e603504c0faf305ab77627af03.html). -3. Run the following and use either connection details stored in the user store or specify the connection details. Details on where to find host, port, and credentials. are covered in the third and fifth steps of the [first tutorial](hana-clients-choose-hana-instance) in this mission. +3. Run the following and use either connection details stored in the user store or specify the connection details. Details on where to find host, port, and credentials are covered in the third and fifth steps of the first tutorial in this mission. - ```Shell (Windows) - java -jar C:\SAP\hdbclient\ngdbc.jar -k USER1UserKey -o encrypt=True -o validatecertificate=false -c "SELECT * FROM HOTELS.CUSTOMER" - ``` + [OPTION BEGIN [Windows]] - Alternatively, you may run + Using a user store key: - ```Shell (Windows) - java -jar C:\SAP\hdbclient\ngdbc.jar -u USER1,Password1 -n your_host:your_port -o encrypt=True -o validatecertificate=false -c "SELECT * FROM HOTELS.CUSTOMER" - ``` + ```Shell + java -jar C:\SAP\hdbclient\ngdbc.jar -k USER1UserKey -o encrypt=True -o validatecertificate=false -c "SELECT * FROM HOTELS.CUSTOMER" + ``` - ```Shell (Linux or Mac) - java -jar ~/sap/hdbclient/ngdbc.jar -u USER1,Password1 -n your_host:your_port -o encrypt=True -o validatecertificate=false -c "SELECT * FROM HOTELS.CUSTOMER" - ``` + Alternatively: + + ```Shell + java -jar C:\SAP\hdbclient\ngdbc.jar -u USER1,Password1 -n your_host:your_port -o encrypt=True -o validatecertificate=false -c "SELECT * FROM HOTELS.CUSTOMER" + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + java -jar ~/sap/hdbclient/ngdbc.jar -u USER1,Password1 -n your_host:your_port -o encrypt=True -o validatecertificate=false -c "SELECT * FROM HOTELS.CUSTOMER" + ``` + + [OPTION END] ![Link text e.g., Destination screen](java-driver-result.png) @@ -107,21 +135,29 @@ See [JDBC Command-Line Connection Options](https://help.sap.com/docs/SAP_HANA_CL ### Create a Java application that queries SAP HANA -1. The following commands create a folder named `java`, enter the newly created directory, create a file named `JavaQuery.java`, and open the file in the Notepad text editor. +1. Create a folder named `java`, enter the directory, create a file named `JavaQuery.java`, and open it in a text editor. - ```Shell (Microsoft Windows) - mkdir %HOMEPATH%\HANAClientsTutorial\java - cd %HOMEPATH%\HANAClientsTutorial\java - notepad JavaQuery.java - ``` + [OPTION BEGIN [Windows]] + + ```Shell + mkdir %HOMEPATH%\HANAClientsTutorial\java + cd %HOMEPATH%\HANAClientsTutorial\java + notepad JavaQuery.java + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] Substitute `pico` below for your preferred text editor. - ```Shell (Linux or Mac) - mkdir -p $HOME/HANAClientsTutorial/java - cd $HOME/HANAClientsTutorial/java - pico JavaQuery.java - ``` + ```Shell + mkdir -p $HOME/HANAClientsTutorial/java + cd $HOME/HANAClientsTutorial/java + pico JavaQuery.java + ``` + + [OPTION END] 2. Copy the following code into `JavaQuery.java`. Then save and exit the file. @@ -175,33 +211,57 @@ See [JDBC Command-Line Connection Options](https://help.sap.com/docs/SAP_HANA_CL } ``` -3. Compile the `.java` file into a `.class` file using the following command: +3. Compile the `.java` file into a `.class` file using the following command. - ```Command Prompt (Microsoft Windows) - javac -cp C:\SAP\hdbclient\ngdbc.jar;. JavaQuery.java - ``` + [OPTION BEGIN [Windows]] - ```Powershell (Microsoft Windows) - javac -cp "C:\SAP\hdbclient\ngdbc.jar;." JavaQuery.java - ``` + Command Prompt: - ```Shell (Linux or Mac) - javac -cp ~/sap/hdbclient/ngdbc.jar:. JavaQuery.java - ``` + ```Shell + javac -cp C:\SAP\hdbclient\ngdbc.jar;. JavaQuery.java + ``` -4. Run `JavaQuery.class` and indicate where the SAP HANA JDBC driver is located. Note that the host, port, UID and PWD will be retrieved from the `hdbuserstore`. + PowerShell: - ```Command Prompt (Microsoft Windows) - java -classpath C:\SAP\hdbclient\ngdbc.jar;. JavaQuery - ``` + ```Shell + javac -cp "C:\SAP\hdbclient\ngdbc.jar;." JavaQuery.java + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + javac -cp ~/sap/hdbclient/ngdbc.jar:. JavaQuery.java + ``` + + [OPTION END] - ```Powershell (Microsoft Windows) - java -classpath "C:\SAP\hdbclient\ngdbc.jar;." JavaQuery - ``` +4. Run `JavaQuery.class` and indicate where the SAP HANA JDBC driver is located. Note that the host, port, UID, and PWD will be retrieved from the `hdbuserstore`. - ```Shell (Linux or Mac) - java -classpath ~/sap/hdbclient/ngdbc.jar:. JavaQuery - ``` + [OPTION BEGIN [Windows]] + + Command Prompt: + + ```Shell + java -classpath C:\SAP\hdbclient\ngdbc.jar;. JavaQuery + ``` + + PowerShell: + + ```Shell + java -classpath "C:\SAP\hdbclient\ngdbc.jar;." JavaQuery + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + java -classpath ~/sap/hdbclient/ngdbc.jar:. JavaQuery + ``` + + [OPTION END] ![Java Query](java-query.png) @@ -227,15 +287,14 @@ Visual Studio Code provides plugins for Java and can be used to debug an applica ![referenced libraries](ref-libraries.png) - The JDBC driver is located at `C:\SAP\hdbclient\ngdbc.jar`. - + The JDBC driver is located in your SAP HANA client installation directory (for example, `C:\SAP\hdbclient\ngdbc.jar` on Windows). 5. Place a breakpoint and then select **Run | Start Debugging**. Notice that the debug view becomes active. Notice that the program stops running at the breakpoint that was set. Step through the code by pressing F10 and observe the variable values in the variables pane. - ![VS Code Debugging](debugging.png) + ![Visual Studio Code debugging](debugging.png) ### Browse SAP HANA using DBeaver @@ -249,15 +308,15 @@ The following steps demonstrate how to configure `DBeaver` to connect to SAP HAN 2. Create a new SAP HANA database connection. - ![New Connection](dbeaver-connect1.png) + ![New connection](dbeaver-connect1.png) Specify the connection type and fill in the **Host** and **Port**. Then press **Test Connection**. You may be asked to download the required SAP HANA client JDBC driver. The driver can also be updated under the **Driver Settings**. - ![Connection Settings](dbeaver-connect2.png) + ![Connection settings](dbeaver-connect2.png) Click on **Connection details** to specify the connection name. - ![Connection Details](dbeaver-connect4.png) + ![Connection details](dbeaver-connect4.png) 3. After finishing the wizard, the catalog of the database can be viewed, and SQL statements can be executed. diff --git a/tutorials/hana-clients-node/hana-clients-node.md b/tutorials/hana-clients-node/hana-clients-node.md index 24b92c5ea..ab7f57b5d 100644 --- a/tutorials/hana-clients-node/hana-clients-node.md +++ b/tutorials/hana-clients-node/hana-clients-node.md @@ -4,7 +4,7 @@ author_name: Dan van Leeuwen author_profile: https://github.com/danielva auto_validation: true time: 20 -tags: [ tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana, programming-tool>node-js] +tags: [tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana, programming-tool>node-js] primary_tag: software-product>sap-hana-cloud --- @@ -40,25 +40,23 @@ If Node.js is installed, the currently installed version is returned, such as v2 If Node.js is not installed, download the long-term support (LTS) version of Node.js from [Download Node.js](https://nodejs.org/en/download/). ->If an install for Node.js is not provided on Linux, you may choose to install it via a package manager. For more details, please navigate to [this link](https://nodejs.org/en/download/package-manager/). +> [!TIP] +> If Node.js is not available through your Linux distribution's standard installation process, you can install it using a package manager. For more details, please navigate to [this link](https://nodejs.org/en/download/package-manager/). ---- +During the installation, there is no need to install tools for native modules. ->During the installation, there is no need to install tools for native modules. -> ->![Chocolatey](Chocolatey.png) +![Chocolatey](Chocolatey.png) ---- +> [!NOTE] +> The SAP HANA client provides a 32-bit and a 64-bit install, as does Node.js. The Node.js driver provided with the SAP HANA client is available for 64-bit only. +> +> For further details on supported versions, see SAP Note [3165810 - SAP HANA Client Supported Platforms](https://launchpad.support.sap.com/#/notes/3165810). ->The SAP HANA client provides a 32-bit and a 64-bit install, as does Node.js. The Node.js driver provided with the SAP HANA client is available for 64-bit only. For further details on supported versions, see SAP Note [3165810 - SAP HANA Client Supported Platforms](https://launchpad.support.sap.com/#/notes/3165810). +Another option is to use a docker image that contains [Node.js](https://github.com/nodejs/docker-node#docker-run) as shown below. ---- - -> Another option is to use a docker image that contains [Node.js](https://github.com/nodejs/docker-node#docker-run) as shown below. -> ->```Shell ->docker run -it --name=nodealpine node:alpine /bin/bash ->``` +```Shell +docker run -it --name=nodealpine node:alpine /bin/bash +``` ### Install SAP HANA client for Node.js from NPM @@ -66,67 +64,97 @@ Node.js packages are available using [NPM](https://www.npmjs.com/), which is the 1. Enter `hana client`, and click **Search**. - ![Search for hana-client](search-hana-client.png) + ![Search for hana client](search-hana-client.png) The page for the SAP HANA Node.js package on npm is shown below. - ![npm page for hana-client](npm-hana-client.png) + ![npm page for hana client](npm-hana-client.png) It contains additional sample code, a weekly download counter, information about previous versions and the command to install the package using the npm command line interface (`cli`). 2. Create a folder named `node` and enter the newly created directory. - ```Shell (Microsoft Windows) - mkdir %HOMEPATH%\HANAClientsTutorial\node - cd %HOMEPATH%\HANAClientsTutorial\node - ``` + [OPTION BEGIN [Windows]] - ```Shell (Linux or Mac) - mkdir -p $HOME/HANAClientsTutorial/node - cd $HOME/HANAClientsTutorial/node - ``` + ```Shell + mkdir %HOMEPATH%\HANAClientsTutorial\node + cd %HOMEPATH%\HANAClientsTutorial\node + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + mkdir -p $HOME/HANAClientsTutorial/node + cd $HOME/HANAClientsTutorial/node + ``` + + [OPTION END] 3. Initialize the project and install the `hana-client` driver from NPM. - ```Shell - npm init -y - npm install @sap/hana-client - ``` + ```Shell + npm init -y + npm install @sap/hana-client + ``` + + > [!NOTE] + > The `hana-client` driver contains native libraries as shown below. - >The `hana-client` driver contains native libraries as shown below. - >![pre built libraries](prebuilt.png) - >When installed using NPM, the native libraries for all available platforms are downloaded. The following environment variable can be used to remove the other platforms reducing the size of the project. For additional details, see [Node.js Environment Variables](https://help.sap.com/docs/SAP_HANA_CLIENT/f1b440ded6144a54ada97ff95dac7adf/2dbfa39ecc364a65a6ab0fea9c8c8bd9.html). - - >```Shell (Microsoft Windows) - >set HDB_NODE_PLATFORM_CLEAN=1 - >npm uninstall @sap/hana-client - >npm install @sap/hana-client - >``` - - > - >```Shell (Linux or Mac) - >export HDB_NODE_PLATFORM_CLEAN=1 - >npm uninstall @sap/hana-client - >npm install @sap/hana-client - >``` - > - >The hana-client driver is also available from the HANA client install folder. The install location was set during the install. - - >```Shell (Microsoft Windows) - >cd C:\SAP\hdbclient\node - >npm install - >cd %HOMEPATH%\HANAClientsTutorial\node - >npm install C:\SAP\hdbclient\node - >``` - > - >```Shell (Linux or Mac) - >cd ~/SAP/hdbclient/node - >npm install - >cd ~/HANAClientsTutorial/node - >npm install ~/SAP/hdbclient/node - >``` - - >If you encounter an error about permissions, on Microsoft Windows, run or open the command prompt as an administrator, or use `sudo` on Linux or Mac. + ![Pre built libraries](prebuilt.png) + When installed using NPM, the native libraries for all available platforms are downloaded. + + > [!TIP] + > The following environment variable can be used to remove the other platforms reducing the size of the project. For additional details, see [Node.js Environment Variables](https://help.sap.com/docs/SAP_HANA_CLIENT/f1b440ded6144a54ada97ff95dac7adf/2dbfa39ecc364a65a6ab0fea9c8c8bd9.html). + + [OPTION BEGIN [Windows]] + + ```Shell + set HDB_NODE_PLATFORM_CLEAN=1 + npm uninstall @sap/hana-client + npm install @sap/hana-client + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + export HDB_NODE_PLATFORM_CLEAN=1 + npm uninstall @sap/hana-client + npm install @sap/hana-client + ``` + + [OPTION END] + + > [!NOTE] + > The hana-client driver is also available from the HANA client install folder. The install location was set during the install. + + [OPTION BEGIN [Windows]] + + ```Shell + cd C:\SAP\hdbclient\node + npm install + cd %HOMEPATH%\HANAClientsTutorial\node + npm install C:\SAP\hdbclient\node + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + cd ~/SAP/hdbclient/node + npm install + cd ~/HANAClientsTutorial/node + npm install ~/SAP/hdbclient/node + ``` + + [OPTION END] + + > [!TIP] + > If you encounter an error about permissions, on Microsoft Windows, run or open the command prompt as an administrator, or use `sudo` on Linux or Mac. 4. The following command lists the Node.js modules that are now installed locally into the `HANAClientsTutorial\node` folder. @@ -136,56 +164,64 @@ Node.js packages are available using [NPM](https://www.npmjs.com/), which is the ![npm list](npm-list.png) -> Some Tips +#### Optional NPM Commands ->At this point, the SAP HANA client module has been installed into the `HANAClientsTutorials\node\node_modules` folder and added as a dependency in the `packages.json` file. The following is some extra optional information on NPM. -> ->Node.js modules can also be installed globally. To see the list of Node.js modules installed globally enter the following command. +At this point, the SAP HANA client module has been installed into the `HANAClientsTutorial\node\node_modules` folder and added as a dependency in the `packages.json` file. The following is some extra optional information on NPM. + +Node.js modules can also be installed globally. To see the list of Node.js modules installed globally enter the following command. ->The depth parameter can be used to specify the number of levels to show when displaying module dependencies. By setting depth=x, a tree-structure is outputted that shows modules that are x levels below the top-level module. +The depth parameter can be used to specify the number of levels to show when displaying module dependencies. By setting depth=x, a tree-structure is outputted that shows modules that are x levels below the top-level module. ->```Shell ->npm list -g ->npm list -g --depth=0 ->``` +```Shell +npm list -g +npm list -g --depth=0 +``` ->Command line help for NPM is available. A few examples of this are shown below. +Command line help for NPM is available. A few examples of this are shown below. ->```Shell ->npm help ->npm help list ->``` +```Shell +npm help +npm help list +``` ->Additional information can be found out for a module, such as the debug module, via the info command. +Additional information can be found out for a module, such as the debug module, via the info command. ->```Shell ->npm info @sap/hana-client ->``` +```Shell +npm info @sap/hana-client +``` ->The following commands can be used to view the latest available version of a package, remove a package, add a specific version of a package and then update it to the latest version. +The following commands can be used to view the latest available version of a package, remove a package, add a specific version of a package and then update it to the latest version. ->```Shell ->npm view @sap/hana-client version ->npm uninstall @sap/hana-client ->npm install @sap/hana-client@2.12.25 ->npm list @sap/hana-client ->npm update @sap/hana-client ->npm list @sap/hana-client ->``` +```Shell +npm view @sap/hana-client version +npm uninstall @sap/hana-client +npm install @sap/hana-client@2.12.25 +npm list @sap/hana-client +npm update @sap/hana-client +npm list @sap/hana-client +``` ### Create a synchronous Node.js application that queries SAP HANA 1. Open a file named `nodeQuery.js` in an editor. - ```Shell (Microsoft Windows) - notepad nodeQuery.js - ``` + [OPTION BEGIN [Windows]] - Substitute `pico` below for your preferred text editor. + ```Shell + notepad nodeQuery.js + ``` - ```Shell (Linux or Mac) - pico nodeQuery.js - ``` + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + Substitute `pico` below for your preferred text editor. + + ```Shell + pico nodeQuery.js + ``` + + [OPTION END] 2. Add the code below to `nodeQuery.js`. Note that the values for host, port, user name and password are provided by the previously configured `hdbuserstore` key USER1UserKey. Save the file when finished. @@ -252,9 +288,9 @@ Node.js packages are available using [NPM](https://www.npmjs.com/), which is the 3. Run the app. - ```Shell - node nodeQuery.js - ``` + ```Shell + node nodeQuery.js + ``` ![Running nodeQuery.js](Node-query.png) @@ -264,40 +300,57 @@ Node.js packages are available using [NPM](https://www.npmjs.com/), which is the 4. To enable debug logging of the SAP HANA Node.js client, enter the following command and then rerun the app. - ```Command Prompt (Microsoft Windows) - set DEBUG=* - node nodeQuery.js - ``` - ```Powershell (Microsoft Windows) - $env:DEBUG='*' - node nodeQuery.js - ``` + [OPTION BEGIN [Windows]] - ```Shell (Linux or Mac) - export DEBUG=* - node nodeQuery.js - ``` + Command Prompt: - ![debug output](debug-flag.png) + ```Shell + set DEBUG=* + node nodeQuery.js + ``` + + PowerShell: + + ```Shell + $env:DEBUG='*' + node nodeQuery.js + ``` The value of the environment variable DEBUG can be seen and removed with the commands below. - ```Command Prompt (Microsoft Windows) - set DEBUG - set DEBUG= - set DEBUG - ``` - ```Powershell (Microsoft Windows) - $env:DEBUG - $env:DEBUG='*' - Remove-Item Env:DEBUG - ``` + Command Prompt: - ```Shell (Linux or Mac) - printenv | grep DEBUG - unset DEBUG - printenv | grep DEBUG - ``` + ```Shell + set DEBUG + set DEBUG= + set DEBUG + ``` + + PowerShell: + + ```Shell + $env:DEBUG + Remove-Item Env:DEBUG + ``` + + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + ```Shell + export DEBUG=* + node nodeQuery.js + ``` + + The value of the environment variable DEBUG can be seen and removed with the commands below. + + ```Shell + printenv | grep DEBUG + unset DEBUG + printenv | grep DEBUG + ``` + + [OPTION END] ### Create a synchronous app that uses a connection pool @@ -305,15 +358,23 @@ Connection pooling can improve performance when making multiple, brief connectio 1. Open a file named `nodeQueryConnectionPool.js` in an editor. - ```Shell (Microsoft Windows) - notepad nodeQueryConnectionPool.js - ``` + [OPTION BEGIN [Windows]] - Substitute `pico` below for your preferred text editor. + ```Shell + notepad nodeQueryConnectionPool.js + ``` - ```Shell (Linux or Mac) - pico nodeQueryConnectionPool.js - ``` + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + Substitute `pico` below for your preferred text editor. + + ```Shell + pico nodeQueryConnectionPool.js + ``` + + [OPTION END] 2. Add the code below to `nodeQueryConnectionPool.js`. Note that the values for host, port, user name and password are provided by the previously configured `hdbuserstore` key USER1UserKey. Save the file when finished. @@ -416,15 +477,23 @@ Asynchronous programming enables non-blocking code execution which is demonstrat 1. Open a file named `nodeQueryCallback.js` in an editor. - ```Shell (Microsoft Windows) - notepad nodeQueryCallback.js - ``` + [OPTION BEGIN [Windows]] - Substitute `pico` below for your preferred text editor. + ```Shell + notepad nodeQueryCallback.js + ``` - ```Shell (Linux or Mac) - pico nodeQueryCallback.js - ``` + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + Substitute `pico` below for your preferred text editor. + + ```Shell + pico nodeQueryCallback.js + ``` + + [OPTION END] 2. Add the code below to `nodeQueryCallback.js`. Note that the values for host, port, user name and password are provided by the previously configured `hdbuserstore` key USER1UserKey. Save the file when finished. @@ -502,9 +571,9 @@ Asynchronous programming enables non-blocking code execution which is demonstrat 3. Run the app. - ```Shell - node nodeQueryCallback.js - ``` + ```Shell + node nodeQueryCallback.js + ``` ![Running nodeQueryCallback.js](Node-query-callback.png) @@ -516,102 +585,110 @@ The Node.js driver for the SAP HANA client added support for promises in the 2.1 1. Open a file named `nodeQueryPromise.js` in an editor. - ```Shell (Microsoft Windows) - notepad nodeQueryPromise.js - ``` - - Substitute `pico` below for your preferred text editor. + [OPTION BEGIN [Windows]] - ```Shell (Linux or Mac) - pico nodeQueryPromise.js - ``` + ```Shell + notepad nodeQueryPromise.js + ``` -2. Add the code below to `nodeQueryPromise.js`. Note that the values for host, port, user name and password are provided by the previously configured `hdbuserstore` key USER1UserKey. Save the file when finished. + [OPTION END] - ```JavaScript - 'use strict'; - var util = require('util'); - var hana = require('@sap/hana-client'); - var PromiseModule = require('@sap/hana-client/extension/Promise.js'); + [OPTION BEGIN [Mac and Linux]] - var connOptions = { - //Option 1, retrieve the connection parameters from the hdbuserstore - serverNode: '@USER1UserKey', //host, port, uid, and pwd retrieved from hdbuserstore + Substitute `pico` below for your preferred text editor. - //Option 2, specify the connection parameters - //serverNode: 'host:port', - //UID: 'USER1', - //PWD: 'Password1', + ```Shell + pico nodeQueryPromise.js + ``` - sslValidateCertificate: 'false', //Must be set to false when connecting to an SAP HANA on-premise instance that uses a self-signed certificate. - }; + [OPTION END] - //Asynchronous example calling a stored procedure that uses the promise module - var connection = hana.createConnection(); - var statement; - - PromiseModule.connect(connection, connOptions) - .then(() => { - //Prepared statement example - return PromiseModule.prepare(connection, 'CALL HOTELS.SHOW_RESERVATIONS(?,?)'); - }) - .then((stmt) => { - statement = stmt; - const parameters = [11, '2020-12-24']; - return PromiseModule.executeQuery(stmt, parameters); - }) - .then((results) => { - return processResults(results); - }) - .then((results) => { - return PromiseModule.close(results); - }) - .then(() => { - return PromiseModule.drop(statement); - }) - .then(() => { - PromiseModule.disconnect(connection); - }) - .catch(err => { - console.error(err); - }); +2. Add the code below to `nodeQueryPromise.js`. Note that the values for host, port, user name and password are provided by the previously configured `hdbuserstore` key USER1UserKey. Save the file when finished. - function processResults(results) { - return new Promise((resolve, reject) => { - var done = false; - PromiseModule.next(results) - .then((hasValues) => { - if (hasValues) { - return PromiseModule.getValues(results); - } - else { - done = true; - } - }) - .then((values) => { - if (done) { - resolve(results); - } - else { - console.log(util.inspect(values, { colors: false })); - processResults(results) - .then((results) => { - resolve(results); - }); - } - }) - .catch (err => { - reject(err); - }); - }) - } - ``` + ```JavaScript + 'use strict'; + var util = require('util'); + var hana = require('@sap/hana-client'); + var PromiseModule = require('@sap/hana-client/extension/Promise.js'); + + var connOptions = { + //Option 1, retrieve the connection parameters from the hdbuserstore + serverNode: '@USER1UserKey', //host, port, uid, and pwd retrieved from hdbuserstore + + //Option 2, specify the connection parameters + //serverNode: 'host:port', + //UID: 'USER1', + //PWD: 'Password1', + + sslValidateCertificate: 'false', //Must be set to false when connecting to an SAP HANA on-premise instance that uses a self-signed certificate. + }; + + //Asynchronous example calling a stored procedure that uses the promise module + var connection = hana.createConnection(); + var statement; + + PromiseModule.connect(connection, connOptions) + .then(() => { + //Prepared statement example + return PromiseModule.prepare(connection, 'CALL HOTELS.SHOW_RESERVATIONS(?,?)'); + }) + .then((stmt) => { + statement = stmt; + const parameters = [11, '2020-12-24']; + return PromiseModule.executeQuery(stmt, parameters); + }) + .then((results) => { + return processResults(results); + }) + .then((results) => { + return PromiseModule.close(results); + }) + .then(() => { + return PromiseModule.drop(statement); + }) + .then(() => { + PromiseModule.disconnect(connection); + }) + .catch(err => { + console.error(err); + }); + + function processResults(results) { + return new Promise((resolve, reject) => { + var done = false; + PromiseModule.next(results) + .then((hasValues) => { + if (hasValues) { + return PromiseModule.getValues(results); + } + else { + done = true; + } + }) + .then((values) => { + if (done) { + resolve(results); + } + else { + console.log(util.inspect(values, { colors: false })); + processResults(results) + .then((results) => { + resolve(results); + }); + } + }) + .catch (err => { + reject(err); + }); + }) + } + ``` 3. Run the app. - ```Shell - node nodeQueryPromise.js - ``` + ```Shell + node nodeQueryPromise.js + ``` ![Running nodeQueryPromise.js](Node-query-promise.png) @@ -635,109 +712,118 @@ Visual Studio Code can run and debug a Node.js application. It is a lightweight Notice that the program stops running at the breakpoint that was set. Observe the variable values in the leftmost pane. Step through code. - ![VS Code Debugging](debugging.png) + ![Debugging in Visual Studio Code](debugging.png) ### Use TypeScript [TypeScript](https://www.typescriptlang.org/) is a superset of JavaScript that provides optional types, compile-time checking, and code completion when using a tool such as Visual Studio Code. The following step provides an example of using TypeScript with the SAP HANA client Node.js interface. -1. Examine the interface file which is located at `C:\SAP\hdbclient\node\lib\index.d.ts` in SAP HANA client versions 2.16 and higher. +1. Examine the interface file which is located in the SAP HANA client node installation directory (for example, `C:\SAP\hdbclient\node\lib\index.d.ts` on Windows) - ![declaration file](ts-declaration-file.png) + ![Declaration file](ts-declaration-file.png) Notice that it contains definitions for the methods of the SAP HANA client Node.js interface. The method `setClientInfo` will be highlighted in substep 6. -2. Open a file named `nodeQueryTS.js` in an editor. +2. Open a file named `nodeQueryTS.ts` in an editor. - ```Shell (Microsoft Windows) - notepad nodeQueryTS.ts - ``` + [OPTION BEGIN [Windows]] - Substitute `pico` below for your preferred text editor. + ```Shell + notepad nodeQueryTS.ts + ``` - ```Shell (Linux or Mac) - pico nodeQueryTS.ts - ``` + [OPTION END] -3. Add the code below to `nodeQueryTS.js`. Note that the values for host, port, user name and password are provided by the previously configured `hdbuserstore` key USER1UserKey. + [OPTION BEGIN [Mac and Linux]] - ```JavaScript - "use strict"; - import * as hana from '@sap/hana-client'; + Substitute `pico` below for your preferred text editor. - var connection: hana.Connection = hana.createConnection(); + ```Shell + pico nodeQueryTS.ts + ``` - var connOptions: hana.ConnectionOptions = { - serverNode: '@USER1UserKey', //host, port, uid, and pwd retrieved from hdbuserstore - //serverNode: '123456-7890-400a-8bbd-41097dfd15ae.hana0.prod-us10.hanacloud.ondemand.com:443', - //UID: 'USER1', - //PWD: 'Password1' - }; + [OPTION END] - connection.connect(connOptions); - connection.setClientInfo("CURRENT_YEAR", 2023); //should be "2023" +3. Add the code below to `nodeQueryTS.ts`. Note that the values for host, port, user name and password are provided by the previously configured `hdbuserstore` key USER1UserKey. - console.log("Year session value is " + connection.getClientInfo("CURRENT_YEAR")); + ```JavaScript + "use strict"; + import * as hana from '@sap/hana-client'; - var sql1: string = "SELECT TITLE, FIRSTNAME, NAME FROM HOTELS.CUSTOMER WHERE FIRSTNAME LIKE ?"; + var connection: hana.Connection = hana.createConnection(); - var statement: hana.Statement = connection.prepare(sql1); - var result1: hana.ResultSet = statement.executeQuery(['M%']); - var moreData: boolean = result1.next(); - while (moreData) { - var row : {[key: string]: string} = result1.getValues(); - console.log(row); - moreData = result1.next(); - } - connection.disconnect(); - ``` + var connOptions: hana.ConnectionOptions = { + serverNode: '@USER1UserKey', //host, port, uid, and pwd retrieved from hdbuserstore + //serverNode: '123456-7890-400a-8bbd-41097dfd15ae.hana0.prod-us10.hanacloud.ondemand.com:443', + //UID: 'USER1', + //PWD: 'Password1' + }; + + connection.connect(connOptions); + connection.setClientInfo("CURRENT_YEAR", 2023); //should be "2023" + + console.log("Year session value is " + connection.getClientInfo("CURRENT_YEAR")); + + var sql1: string = "SELECT TITLE, FIRSTNAME, NAME FROM HOTELS.CUSTOMER WHERE FIRSTNAME LIKE ?"; + + var statement: hana.Statement = connection.prepare(sql1); + var result1: hana.ResultSet = statement.executeQuery(['M%']); + var moreData: boolean = result1.next(); + while (moreData) { + var row : {[key: string]: string} = result1.getValues(); + console.log(row); + moreData = result1.next(); + } + connection.disconnect(); + ``` 4. Check if TypeScript is already installed and if not install it. - ```Shell - tsc -version - ``` + ```Shell + tsc -version + ``` If the TypeScript is installed, a version value will be returned. - ![typescript version](typescript-version.png) + ![Typescript version](typescript-version.png) If TypeScript is not installed, it can be installed globally with the below command. - ```Shell - npm install -g typescript - ``` + ```Shell + npm install -g typescript + ``` 5. Add the types module. First check the Node.js version, determine what modules are in the current project, and what are the available versions of `@types/node`. - ```Shell - npm info @types/node - ``` + ```Shell + npm info @types/node + ``` Install the @types/node module which provides type definitions for Node.js. - ```Shell - npm install @types/node - node -v - npm list - ``` + ```Shell + npm install @types/node + node -v + npm list + ``` ![node and module versions](npm-list-new.png) - >The major version of Node.js and the `@types/node` versions should match. If you need to uninstall `@types/node` and install a different version, an example is shown below of the commands to do so. + > [!NOTE] + > The major version of Node.js and the `@types/node` versions should match. If you need to uninstall `@types/node` and install a different version, an example is shown below of the commands to do so. - >```Shell - >npm uninstall @types/node - >npm install @types/node@18.15.11 - >``` + ```Shell + npm uninstall @types/node + npm install @types/node@18.15.11 + ``` 6. Run the TypeScript compiler and notice that it finds an error. - ```Shell - tsc nodeQueryTS.ts - ``` + ```Shell + tsc nodeQueryTS.ts + ``` ![Typescript error](tsc-year-error-new.png) @@ -753,10 +839,10 @@ Visual Studio Code can run and debug a Node.js application. It is a lightweight 9. Correct the error, compile, and run the app using the following commands. The error can be corrected by changing 2023 to "2023". - ```Shell - tsc nodeQueryTS.ts - node nodeQueryTS.js - ``` + ```Shell + tsc nodeQueryTS.ts + node nodeQueryTS.js + ``` ![Running node application](node-query-ts-execute.png) diff --git a/tutorials/hana-clients-odbc/hana-clients-odbc.md b/tutorials/hana-clients-odbc/hana-clients-odbc.md index e57d375ed..e6d0e349e 100644 --- a/tutorials/hana-clients-odbc/hana-clients-odbc.md +++ b/tutorials/hana-clients-odbc/hana-clients-odbc.md @@ -4,7 +4,7 @@ author_name: Dan van Leeuwen author_profile: https://github.com/danielva auto_validation: true time: 15 -tags: [ tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana] +tags: [tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana] primary_tag: software-product>sap-hana-cloud --- @@ -33,9 +33,10 @@ The ODBC Data Source Administrator lists the installed ODBC drivers and the conf 1. Open the administrator by entering ODBC after clicking on the Microsoft Windows start icon. - >Ensure that you choose the 64-bit version if you have the 64-bit version of the SAP HANA client installed. + > [!NOTE] + > Ensure that you choose the 64-bit version if you have the 64-bit version of the SAP HANA client installed. - ![start ODBC Administrator](start-odbc.png) + ![Start the ODBC Administrator](start-odbc.png) 2. Click the **Drivers** tab and view the installed drivers. @@ -53,8 +54,10 @@ The ODBC Data Source Administrator lists the installed ODBC drivers and the conf ![New data source](Create-new-data-source.png) -6. Example data source configuration for SAP HANA Cloud. - >For the host, paste the SQL Endpoint from your instance. For more details, review [Choose an SAP HANA Database](https://developers.sap.com/tutorials/hana-clients-choose-hana-instance.html). +6. Example data source configuration for SAP HANA Cloud. + + > [!NOTE] + > For the host, paste the SQL Endpoint from your instance. For more details, review [Choose an SAP HANA Database](https://developers.sap.com/tutorials/hana-clients-choose-hana-instance.html). ![ODBC HANA Cloud](ODBC-HC.png) @@ -72,7 +75,8 @@ The ODBC Data Source Administrator lists the installed ODBC drivers and the conf 9. Press OK to save the data source. - >Saved values can also be viewed using the Microsoft Windows registry editor under the key `Computer\HKEY_CURRENT_USER\Software\ODBC\ODBC.INI`. + > [!NOTE] + > Saved values can also be viewed using the Microsoft Windows registry editor under the key `Computer\HKEY_CURRENT_USER\Software\ODBC\ODBC.INI`. For additional details see [Connect to SAP HANA via ODBC](https://help.sap.com/docs/SAP_HANA_CLIENT/f1b440ded6144a54ada97ff95dac7adf/66a4169b84b2466892e1af9781049836.html). @@ -88,53 +92,58 @@ The following instructions demonstrate how [unixODBC](http://www.unixodbc.org/) 2. On a Mac, unixODBC can be installed using [Homebrew](https://brew.sh). - ```Shell (Mac) - brew install unixodbc - ``` + [OPTION BEGIN [Mac]] + + ```Shell + brew install unixodbc + ``` + + [OPTION END] 3. The following commands can be used to confirm that unixODBC is installed, determine the location of the .odbc.ini file (if it exists), and to confirm the location of the SAP HANA client install that contains the ODBC driver. - ```Shell (Linux or Mac) - odbcinst -j - which hdbsql - ``` + ```Shell + odbcinst -j + which hdbsql + ``` ![odbcinst](odbcinst.png) 4. Navigate to a directory, similar to the first one that is highlighted in the screenshot above. - ```Shell (Linux or Mac) - cd $HOME - ``` + ```Shell + cd $HOME + ``` 5. Edit the `.odbc.ini` file (or create it if it does not exist) to add one or more data sources. Be sure to configure the values of `servernode` and `driver` so that they conform with your setup. - >The driver's file extension is `dylib` instead of `so` on a Mac. + > [!NOTE] + > The driver's file extension is `dylib` instead of `so` on a Mac. - ```.odbc.ini - [HANA_Cloud] - servernode = 6b7ae0da-ee5a-4782-bc7e-297099099b59.hana.prod-ca10.hanacloud.ondemand.com:443 - driver = /home/dan/sap/hdbclient/libodbcHDB.so - encrypt = true - sslValidateCertificate = true + ```.odbc.ini + [HANA_Cloud] + servernode = 6b7ae0da-ee5a-4782-bc7e-297099099b59.hana.prod-ca10.hanacloud.ondemand.com:443 + driver = /home/dan/sap/hdbclient/libodbcHDB.so + encrypt = true + sslValidateCertificate = true - [HANA_OnPremise] - servernode = hxehost:39015 - driver = /home/dan/sap/hdbclient/libodbcHDB.so - databasename = HXE - ``` + [HANA_OnPremise] + servernode = hxehost:39015 + driver = /home/dan/sap/hdbclient/libodbcHDB.so + databasename = HXE + ``` 6. unixODBC provides a basic SQL query tool called `isql` that can be used to validate a data source. - ```Shell (Linux or Mac) - isql -v HANA_Cloud User1 Password1 - ``` + ```Shell + isql -v HANA_Cloud User1 Password1 + ``` Once you see a message that indicates a connection has been made, enter the following statement to verify this. - ```Shell (Linux or Mac) - SELECT * FROM HOTELS.CUSTOMER - ``` + ```Shell + SELECT * FROM HOTELS.CUSTOMER + ``` ![isql](isqlQuery.png) @@ -142,11 +151,14 @@ The following instructions demonstrate how [unixODBC](http://www.unixodbc.org/) An application that supports ODBC can now make use of the created data source. One example on Windows is Microsoft Excel. ->Microsoft Excel can be 32 or 64 bit. This can be seen under **File | Account | About Excel**. +> [!NOTE] +> Microsoft Excel and the SAP HANA client must use the same architecture (both 32-bit or both 64-bit). > -> ![Excel 64 bit](excel-64-bit.png) -> -> The SAP HANA client install can also be 32 or 64 bit. To connect, the versions of SAP HANA client and Microsoft Excel must match. If needed, the 32-bit installer for SAP HANA client is available from the [SAP Software Centre](https://me.sap.com/softwarecenter) site and can be installed into a separate directory such as `C:\SAP\hdbclient32`. +> The Excel version can be checked under **File | Account | About Excel**. + +![Excel 64 bit](excel-64-bit.png) + +If needed, the 32-bit installer for SAP HANA client is available from the [SAP Software Centre](https://me.sap.com/softwarecenter) site and can be installed into a separate directory such as `C:\SAP\hdbclient32`. The following steps demonstrate how to use Microsoft Excel to query data in SAP HANA using the ODBC connector. diff --git a/tutorials/hana-clients-python/hana-clients-python.md b/tutorials/hana-clients-python/hana-clients-python.md index 142340c06..217e40b82 100644 --- a/tutorials/hana-clients-python/hana-clients-python.md +++ b/tutorials/hana-clients-python/hana-clients-python.md @@ -4,7 +4,7 @@ author_name: Dan van Leeuwen author_profile: https://github.com/danielva auto_validation: true time: 15 -tags: [ tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana, programming-tool>python] +tags: [tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana, programming-tool>python] primary_tag: software-product>sap-hana-cloud --- @@ -64,13 +64,19 @@ pip3 --version pip3 install --upgrade pip ``` ->On Linux or Mac, if you encounter permission issues, one way to solve the issue is to use `sudo` before the command. -> ->On Linux, if Python is installed but pip is not, it can be installed on openSUSE using Zypper as shown below. +> [!TIP] +> On Linux or Mac, if you encounter permission issues, one way to solve the issue is to use `sudo` before the command. ->```Shell (Linux) ->zypper install python3-pip ->``` +[OPTION BEGIN [Linux]] + +> [!NOTE] +> If Python is installed but pip is not, it can be installed on openSUSE using Zypper as shown below. + +```Shell +zypper install python3-pip +``` + +[OPTION END] The repository that contains Python packages is [PyPI](https://pypi.org/project/hdbcli/) and includes a package for the SAP HANA client for Python. @@ -82,62 +88,74 @@ Run the following command to download and install the SAP HANA client for Python pip install hdbcli ``` ->If an error is displayed that mentions "No matching distribution found for `hdbcli`, an alternate method is to install it from the SAP HANA client install folder as shown below. -> ->Ensure that the filename is correct in the install command below because it might change depending on the version of `hdbcli` that you have. -> -> ```Shell -> cd C:\SAP\hdbclient -> pip install hdbcli-2.20.15.zip -> ``` - -> If the install still fails, check [3165810 - SAP HANA Client Supported Platforms](https://launchpad.support.sap.com/#/notes/3165810) to ensure that a supported version of Python installed. -> -> To upgrade to the latest available version, enter the following command: -> ```Shell -> pip install --no-cache-dir --upgrade hdbcli -> ``` -> -> To uninstall `hdbcli`, run the following command: -> ```Shell -> pip uninstall hdbcli -> ``` -> -> A specific version can be installed using the following command. -> -> ```Shell -> pip install hdbcli==2.18.22 -> ``` -> -> The list of installed packages can be shown with the following command. -> -> ```Shell -> pip list -> ``` -> -> Details of an installed package such as `hdbcli` can be shown with the following command. -> -> ```Shell -> pip show hdbcli -> ``` +> [!NOTE] +> If an error is displayed that mentions "No matching distribution found for `hdbcli`", an alternate method is to install it from the SAP HANA client install folder as shown below. + +```Shell +cd C:\SAP\hdbclient +pip install hdbcli-2.20.15.zip +``` + +> [!NOTE] +> If the installation still fails, check [3165810 - SAP HANA Client Supported Platforms](https://launchpad.support.sap.com/#/notes/3165810) to ensure that a supported version of Python installed. + +#### Optional hdbcli Package Commands + +To upgrade to the latest available version, enter the following command: + +```Shell +pip install --no-cache-dir --upgrade hdbcli +``` + +To uninstall `hdbcli`, run the following command: + +```Shell +pip uninstall hdbcli +``` + +A specific version can be installed using the following command. + +```Shell +pip install hdbcli==2.18.22 +``` + +The list of installed packages can be shown with the following command. + +```Shell +pip list +``` + +Details of an installed package such as `hdbcli` can be shown with the following command. + +```Shell +pip show hdbcli +``` ### Create Python application that queries SAP HANA -1. In a shell, create a folder named `python`, enter the newly created directory, and open a file name `pythonQuery.py` in an editor. +1. In a shell, create a folder named `python`, enter the newly created directory, and open a file named `pythonQuery.py` in an editor. - ```Shell (Microsoft Windows) - mkdir %HOMEPATH%\HANAClientsTutorial\python - cd %HOMEPATH%\HANAClientsTutorial\python - notepad pythonQuery.py - ``` + [OPTION BEGIN [Windows]] - Substitute `pico` below for your preferred text editor. + ```Shell + mkdir %HOMEPATH%\HANAClientsTutorial\python + cd %HOMEPATH%\HANAClientsTutorial\python + notepad pythonQuery.py + ``` - ```Shell (Linux or Mac) - mkdir -p $HOME/HANAClientsTutorial/python - cd $HOME/HANAClientsTutorial/python - pico pythonQuery.py - ``` + [OPTION END] + + [OPTION BEGIN [Mac and Linux]] + + Substitute `pico` below for your preferred text editor. + + ```Shell + mkdir -p $HOME/HANAClientsTutorial/python + cd $HOME/HANAClientsTutorial/python + pico pythonQuery.py + ``` + + [OPTION END] 2. Add the code below to `pythonQuery.py`. @@ -208,11 +226,12 @@ pip install hdbcli python pythonQuery.py ``` - >On some Linux distributions, python refers to a 2.x version of Python. If so, replace `python` with `python3`. + > [!NOTE] + > On some Linux distributions, python refers to a 2.x version of Python. If so, replace `python` with `python3`. - ![python Query](python-app.png) + ![Python query](python-app.png) -The code in `pythonQuery.py` uses [PEP 249 -- Python Database API Specification](https://www.python.org/dev/peps/pep-0249/), which defines a set of methods that provide a consistent database interface, independent of the actual database being used. +The code in `pythonQuery.py` uses [PEP 249 -- Python Database API Specification](https://www.python.org/dev/peps/pep-0249/), which defines a set of methods that provide a consistent database interface, independent of the actual database being used. - For further examples of accessing a database from Python, see [Python and SQL](https://www.python-course.eu/sql_python.php) and [Python MySQL](https://www.w3schools.com/python/python_mysql_insert.asp). @@ -232,7 +251,7 @@ Visual Studio Code provides plugins for Python and can be used to debug an appli 3. Open the file `pythonQuery.py`. - ![Python Extension](extension.png) + ![Python extension](extension.png) If necessary, Visual Studio Code will recognize the `py` file extension and will suggest installing the Python extension. Click **Install**. @@ -244,11 +263,10 @@ Visual Studio Code provides plugins for Python and can be used to debug an appli Observe the variable values in the leftmost pane. Step through code. - ![VS Code Debugging](debugging.png) + ![Debugging in Visual Studio Code](debugging.png) ### Knowledge check Congratulations! You have now created and debugged a Python application that connects to and queries an SAP HANA database. - --- diff --git a/tutorials/hana-clients-routing/hana-clients-routing.md b/tutorials/hana-clients-routing/hana-clients-routing.md index 9ca9634a5..2e9ff7849 100644 --- a/tutorials/hana-clients-routing/hana-clients-routing.md +++ b/tutorials/hana-clients-routing/hana-clients-routing.md @@ -4,7 +4,7 @@ author_name: Dan van Leeuwen author_profile: https://github.com/danielva auto_validation: true time: 30 -tags: [ tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, tutorial>license] +tags: [tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, tutorial>license] primary_tag: software-product>sap-hana-cloud --- @@ -66,12 +66,12 @@ Individual read only queries can be routed to the replica. There are some condi 1. Verify the version of the SAP HANA client which needs to be 2.28 or higher by executing the below SQL and that the isolation level is [read committed](https://help.sap.com/docs/hana-cloud-database/sap-hana-cloud-sap-hana-database-sql-reference-guide/set-transaction-statement-transaction-management). - ```SQL - SELECT CLIENT_VERSION, CLIENT_APPLICATION, * FROM M_CONNECTIONS WHERE CONNECTION_ID = CURRENT_CONNECTION; - SELECT ISOLATION_LEVEL FROM M_TRANSACTIONS WHERE CONNECTION_ID = CURRENT_CONNECTION; - --SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; - --SET TRANSACTION ISOLATION LEVEL READ COMMITTED; - ``` + ```SQL + SELECT CLIENT_VERSION, CLIENT_APPLICATION, * FROM M_CONNECTIONS WHERE CONNECTION_ID = CURRENT_CONNECTION; + SELECT ISOLATION_LEVEL FROM M_TRANSACTIONS WHERE CONNECTION_ID = CURRENT_CONNECTION; + --SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; + --SET TRANSACTION ISOLATION LEVEL READ COMMITTED; + ``` ![client version](client-version.png) @@ -79,21 +79,21 @@ Individual read only queries can be routed to the replica. There are some condi 2. Execute the below SQL to create and populate a table named MYTABLE. - ```SQL - CREATE TABLE MYTABLE (C1 INT GENERATED BY DEFAULT AS IDENTITY, T1 TIMESTAMP); - INSERT INTO MYTABLE(T1) VALUES(CURRENT_TIMESTAMP); - SELECT * FROM MYTABLE; - ``` + ```SQL + CREATE TABLE MYTABLE (C1 INT GENERATED BY DEFAULT AS IDENTITY, T1 TIMESTAMP); + INSERT INTO MYTABLE(T1) VALUES(CURRENT_TIMESTAMP); + SELECT * FROM MYTABLE; + ``` This table and its contents will be available on both the source and replica. 3. Execute the below SQL to perform a query against the source node and the replica node. Notice that the second SQL statement uses a hint to direct the query to be executed on the replica. The built-in function [STATEMENT_EXECUTION_HOST](https://help.sap.com/docs/hana-cloud-database/sap-hana-cloud-sap-hana-database-sql-reference-guide/statement-execution-host-function-miscellaneous?locale=en-US) identifies the host node that the query ran on. - ```SQL - SELECT * FROM M_VOLUMES; - SELECT C1 AS QUERY_ON_PRIMARY, STATEMENT_EXECUTION_HOST() FROM MYTABLE; - SELECT C1 AS QUERY_ON_REPLICA, STATEMENT_EXECUTION_HOST() FROM MYTABLE WITH HINT (RESULT_LAG('hana_sr')); - ``` + ```SQL + SELECT * FROM M_VOLUMES; + SELECT C1 AS QUERY_ON_PRIMARY, STATEMENT_EXECUTION_HOST() FROM MYTABLE; + SELECT C1 AS QUERY_ON_REPLICA, STATEMENT_EXECUTION_HOST() FROM MYTABLE WITH HINT (RESULT_LAG('hana_sr')); + ``` The source and replica can change so it is important to check the M_VOLUMES monitoring view. @@ -107,34 +107,34 @@ Individual read only queries can be routed to the replica. There are some condi A few additional queries that can be used to gather details about the instance currently connected to are included below. - ```SQL - SELECT * FROM M_SERVICES; - SELECT * FROM M_CONNECTIONS WHERE CONNECTION_ID = CURRENT_CONNECTION; - SELECT DISTINCT S.VOLUME_REPLICATION_ROLE - FROM - M_CONNECTIONS AS C - INNER JOIN - M_SERVICES AS S - ON S.HOST = C.HOST - AND S.PORT = C.PORT - WHERE CONNECTION_ID = CURRENT_CONNECTION AND SERVICE_NAME = 'indexserver' - AND own = 'TRUE'; - ``` + ```SQL + SELECT * FROM M_SERVICES; + SELECT * FROM M_CONNECTIONS WHERE CONNECTION_ID = CURRENT_CONNECTION; + SELECT DISTINCT S.VOLUME_REPLICATION_ROLE + FROM + M_CONNECTIONS AS C + INNER JOIN + M_SERVICES AS S + ON S.HOST = C.HOST + AND S.PORT = C.PORT + WHERE CONNECTION_ID = CURRENT_CONNECTION AND SERVICE_NAME = 'indexserver' + AND own = 'TRUE'; + ``` 4. Examine the M_SQL_PLAN_CACHE view of the source and replica. Views prefixed with M_ are monitoring views. The view [M_SQL_PLAN_CACHE](https://help.sap.com/docs/hana-cloud-database/sap-hana-cloud-sap-hana-database-sql-reference-guide/m-sql-plan-cache-system-view?locale=en-US) provides execution plan statistics. _SYS_VR_REPLICA is a schema prefix used to access monitoring views that reside on a replica node. - ```SQL - SELECT HOST, STATEMENT_STRING, USER_NAME, LAST_EXECUTION_TIMESTAMP FROM SYS.M_SQL_PLAN_CACHE WHERE - STATEMENT_STRING LIKE '%MYTABLE%' ORDER BY LAST_EXECUTION_TIMESTAMP DESC; - --Notice that both statements appear but only the first one is executed + ```SQL + SELECT HOST, STATEMENT_STRING, USER_NAME, LAST_EXECUTION_TIMESTAMP FROM SYS.M_SQL_PLAN_CACHE WHERE + STATEMENT_STRING LIKE '%MYTABLE%' ORDER BY LAST_EXECUTION_TIMESTAMP DESC; + --Notice that both statements appear but only the first one is executed - SELECT HOST, STATEMENT_STRING, USER_NAME, LAST_EXECUTION_TIMESTAMP FROM _SYS_VR_REPLICA.M_SQL_PLAN_CACHE WHERE - STATEMENT_STRING LIKE '%MYTABLE%' ORDER BY LAST_EXECUTION_TIMESTAMP DESC; - --Notice that only the statement routed to the replica appears with this query + SELECT HOST, STATEMENT_STRING, USER_NAME, LAST_EXECUTION_TIMESTAMP FROM _SYS_VR_REPLICA.M_SQL_PLAN_CACHE WHERE + STATEMENT_STRING LIKE '%MYTABLE%' ORDER BY LAST_EXECUTION_TIMESTAMP DESC; + --Notice that only the statement routed to the replica appears with this query - --ALTER SYSTEM CLEAR SQL PLAN CACHE; - --with hint(ignore_plan_cache) - ``` + --ALTER SYSTEM CLEAR SQL PLAN CACHE; + --with hint(ignore_plan_cache) + ``` ![querying M_SQL_PLAN_CACHE](M_SQL_PLAN_CACHE.png) @@ -146,36 +146,36 @@ Individual read only queries can be routed to the replica. There are some condi 6. Execute the following SQL to create two stored procedures, one that can be routed to a replica and one that cannot. - ```SQL - CREATE OR REPLACE PROCEDURE QUERY_PROC() - LANGUAGE SQLSCRIPT - READS SQL DATA - AS - BEGIN - SELECT COUNT(*), STATEMENT_EXECUTION_HOST() FROM MYTABLE; - END; - - CREATE OR REPLACE PROCEDURE INSERT_PROC() - LANGUAGE SQLSCRIPT AS - BEGIN - INSERT INTO MYTABLE(T1) VALUES(CURRENT_TIMESTAMP); - SELECT COUNT(*), STATEMENT_EXECUTION_HOST() FROM MYTABLE; - END; - ``` + ```SQL + CREATE OR REPLACE PROCEDURE QUERY_PROC() + LANGUAGE SQLSCRIPT + READS SQL DATA + AS + BEGIN + SELECT COUNT(*), STATEMENT_EXECUTION_HOST() FROM MYTABLE; + END; + + CREATE OR REPLACE PROCEDURE INSERT_PROC() + LANGUAGE SQLSCRIPT AS + BEGIN + INSERT INTO MYTABLE(T1) VALUES(CURRENT_TIMESTAMP); + SELECT COUNT(*), STATEMENT_EXECUTION_HOST() FROM MYTABLE; + END; + ``` Notice above that the first procedure contains the declaration READS SQL DATA which indicates that it does not modify the schema or data while the second stored procedure does insert data into the table. Further details on the syntax is available at [CREATE PROCEDURE Statement](https://help.sap.com/docs/HANA_CLOUD_DATABASE_CN/1bb35593d1e54ce48b4f8ce071594d5e/20d467407519101484f190f545d54b24.html?locale=en-US). 7. Execute the two stored procedures and examine where they are executed. - ```SQL + ```SQL CALL QUERY_PROC() WITH HINT (RESULT_LAG('hana_sr')); - ``` + ``` - ![Call QUERY_PROC](call-query-proc.png) + ![Call QUERY_PROC](call-query-proc.png) - ```SQL - CALL INSERT_PROC() WITH HINT (RESULT_LAG('hana_sr')); - ``` + ```SQL + CALL INSERT_PROC() WITH HINT (RESULT_LAG('hana_sr')); + ``` ![CALL INSERT_PROC](call-insert-proc.png) @@ -189,18 +189,18 @@ A connection can be made directly to the replica so that individual statements d ![Advanced connection options in the SQL Console](direct-connect-sql-console.png) - ``` - replicationRole=REPLICA - ``` + ``` + replicationRole=REPLICA + ``` ![Advanced connection options in the SQL Console](direct-connect-sql-console2.png) Execute the below SQL. - ```SQL - SELECT C1 AS QUERY_ON_REPLICA, STATEMENT_EXECUTION_HOST() FROM MYTABLE; - INSERT INTO MYTABLE(T1) VALUES(CURRENT_TIMESTAMP); - ``` + ```SQL + SELECT C1 AS QUERY_ON_REPLICA, STATEMENT_EXECUTION_HOST() FROM MYTABLE; + INSERT INTO MYTABLE(T1) VALUES(CURRENT_TIMESTAMP); + ``` ![Advanced connection options in the SQL Console](direct-connect-sql-console3.png) @@ -208,9 +208,9 @@ A connection can be made directly to the replica so that individual statements d 2. The below example uses [hdbsql](https://help.sap.com/docs/SAP_HANA_CLIENT/f1b440ded6144a54ada97ff95dac7adf/c2a6d9cbbb5710148afea455ba5746c0.html) which is an interactive command line tool for executing SQL that is part of the SAP HANA Client to connect directly to the replica. - ```Shell - hdbsql -Z replicationRole=REPLICA -A -n 650b653f-d665-44c1-a03c-abf9c23fa60f.hana.prod-us30.hanacloud.ondemand.com:443 -u YOUR_NAME -p Password1 - ``` + ```Shell + hdbsql -Z replicationRole=REPLICA -A -n 650b653f-d665-44c1-a03c-abf9c23fa60f.hana.prod-us30.hanacloud.ondemand.com:443 -u YOUR_NAME -p Password1 + ``` ![Direct Connect with DBISQL](direct-connect-dbisql.png) @@ -220,47 +220,47 @@ The usage monitor app can be used to view metrics such as CPU or memory of the s 1. Change the SQL Console connection back to the source node as the below SQL creates a new table and inserts data which must be executed on the source node. - ``` - replicationRole=SOURCE - ``` + ``` + replicationRole=SOURCE + ``` ![connect to the source](connect-to-source.png) 2. Execute the below to cause a brief spike in CPU usage on the replica and then view the CPU metric in the usage monitor. - ```SQL - CREATE TABLE MYTABLE2(VAL1 DOUBLE); - --Demonstrates how an expensive query is made using cross joins - INSERT INTO MYTABLE2 VALUES(1); - INSERT INTO MYTABLE2 VALUES(2); - INSERT INTO MYTABLE2 VALUES(3); - SELECT * FROM MYTABLE2 T1, MYTABLE2 T2, MYTABLE2 T3; - - CREATE OR REPLACE PROCEDURE POPULATE_MYTABLE2(NUMOFROWS INT) LANGUAGE SQLSCRIPT AS - BEGIN - DECLARE i INT; - TRUNCATE TABLE MYTABLE2; - FOR i IN 1 .. :NUMOFROWS DO - INSERT INTO MYTABLE2 VALUES(RAND_SECURE()); - END FOR; - END; - - CREATE OR REPLACE PROCEDURE CPU_AND_MEMORY_SPIKE() LANGUAGE SQLSCRIPT READS SQL DATA AS - BEGIN - WITH - A AS (SELECT DISTINCT VAL1 AS A1 FROM MYTABLE2 ORDER BY VAL1 DESC), - B AS (SELECT DISTINCT VAL1 AS B1 FROM MYTABLE2 ORDER BY VAL1 ASC), - C AS (SELECT DISTINCT VAL1 AS C1 FROM MYTABLE2 ORDER BY VAL1 DESC) - SELECT TOP 1 DISTINCT A1 + B1 + C1 FROM A, B, C; - END; - - CALL POPULATE_MYTABLE2(750); - CALL CPU_AND_MEMORY_SPIKE() WITH HINT (RESULT_LAG('hana_sr')); --takes about 12 seconds to run - CALL CPU_AND_MEMORY_SPIKE() WITH HINT (RESULT_LAG('hana_sr')); - CALL CPU_AND_MEMORY_SPIKE() WITH HINT (RESULT_LAG('hana_sr')); - CALL CPU_AND_MEMORY_SPIKE() WITH HINT (RESULT_LAG('hana_sr')); - CALL CPU_AND_MEMORY_SPIKE() WITH HINT (RESULT_LAG('hana_sr')); - ``` + ```SQL + CREATE TABLE MYTABLE2(VAL1 DOUBLE); + --Demonstrates how an expensive query is made using cross joins + INSERT INTO MYTABLE2 VALUES(1); + INSERT INTO MYTABLE2 VALUES(2); + INSERT INTO MYTABLE2 VALUES(3); + SELECT * FROM MYTABLE2 T1, MYTABLE2 T2, MYTABLE2 T3; + + CREATE OR REPLACE PROCEDURE POPULATE_MYTABLE2(NUMOFROWS INT) LANGUAGE SQLSCRIPT AS + BEGIN + DECLARE i INT; + TRUNCATE TABLE MYTABLE2; + FOR i IN 1 .. :NUMOFROWS DO + INSERT INTO MYTABLE2 VALUES(RAND_SECURE()); + END FOR; + END; + + CREATE OR REPLACE PROCEDURE CPU_AND_MEMORY_SPIKE() LANGUAGE SQLSCRIPT READS SQL DATA AS + BEGIN + WITH + A AS (SELECT DISTINCT VAL1 AS A1 FROM MYTABLE2 ORDER BY VAL1 DESC), + B AS (SELECT DISTINCT VAL1 AS B1 FROM MYTABLE2 ORDER BY VAL1 ASC), + C AS (SELECT DISTINCT VAL1 AS C1 FROM MYTABLE2 ORDER BY VAL1 DESC) + SELECT TOP 1 DISTINCT A1 + B1 + C1 FROM A, B, C; + END; + + CALL POPULATE_MYTABLE2(750); + CALL CPU_AND_MEMORY_SPIKE() WITH HINT (RESULT_LAG('hana_sr')); --takes about 12 seconds to run + CALL CPU_AND_MEMORY_SPIKE() WITH HINT (RESULT_LAG('hana_sr')); + CALL CPU_AND_MEMORY_SPIKE() WITH HINT (RESULT_LAG('hana_sr')); + CALL CPU_AND_MEMORY_SPIKE() WITH HINT (RESULT_LAG('hana_sr')); + CALL CPU_AND_MEMORY_SPIKE() WITH HINT (RESULT_LAG('hana_sr')); + ``` 3. On the instance details page, select the usage monitor app by selecting either the Memory or Compute and expand the replica section to view the usage. Notice below that we can see the usage is occurring in the replica. @@ -274,50 +274,50 @@ The following example demonstrates creating a workload class that enables querie 1. Execute the below SQL - ```SQL - CREATE WORKLOAD CLASS "WLC_TIMEOUT_SOURCE"; - CREATE WORKLOAD CLASS "WLC_TIMEOUT_REPLICA"; + ```SQL + CREATE WORKLOAD CLASS "WLC_TIMEOUT_SOURCE"; + CREATE WORKLOAD CLASS "WLC_TIMEOUT_REPLICA"; - ALTER WORKLOAD CLASS "WLC_TIMEOUT_SOURCE" SET 'STATEMENT TIMEOUT' = '2'; - ALTER WORKLOAD CLASS "WLC_TIMEOUT_REPLICA" SET 'STATEMENT TIMEOUT' = '4'; + ALTER WORKLOAD CLASS "WLC_TIMEOUT_SOURCE" SET 'STATEMENT TIMEOUT' = '2'; + ALTER WORKLOAD CLASS "WLC_TIMEOUT_REPLICA" SET 'STATEMENT TIMEOUT' = '4'; - SELECT USER_NAME, CLIENT_APPLICATION FROM M_CONNECTIONS WHERE CONNECTION_ID = CURRENT_CONNECTION; - CREATE WORKLOAD MAPPING "WLM_SOURCE" WORKLOAD CLASS "WLC_TIMEOUT_SOURCE" SET 'USER NAME' = 'YOUR_NAME', 'APPLICATION NAME' = 'SAP_HANARuntimeTools_HRA', 'VOLUME REPLICATION ROLE' = 'SOURCE'; - CREATE WORKLOAD MAPPING "WLM_REPLICA" WORKLOAD CLASS "WLC_TIMEOUT_REPLICA" SET 'USER NAME' = 'YOUR_NAME', 'APPLICATION NAME' = 'SAP_HANARuntimeTools_HRA', 'VOLUME REPLICATION ROLE' = 'REPLICA'; + SELECT USER_NAME, CLIENT_APPLICATION FROM M_CONNECTIONS WHERE CONNECTION_ID = CURRENT_CONNECTION; + CREATE WORKLOAD MAPPING "WLM_SOURCE" WORKLOAD CLASS "WLC_TIMEOUT_SOURCE" SET 'USER NAME' = 'YOUR_NAME', 'APPLICATION NAME' = 'SAP_HANARuntimeTools_HRA', 'VOLUME REPLICATION ROLE' = 'SOURCE'; + CREATE WORKLOAD MAPPING "WLM_REPLICA" WORKLOAD CLASS "WLC_TIMEOUT_REPLICA" SET 'USER NAME' = 'YOUR_NAME', 'APPLICATION NAME' = 'SAP_HANARuntimeTools_HRA', 'VOLUME REPLICATION ROLE' = 'REPLICA'; - --DROP WORKLOAD MAPPING "WLM_SOURCE"; - --DROP WORKLOAD MAPPING "WLM_REPLICA"; + --DROP WORKLOAD MAPPING "WLM_SOURCE"; + --DROP WORKLOAD MAPPING "WLM_REPLICA"; - ALTER WORKLOAD CLASS "WLC_TIMEOUT_SOURCE" ENABLE; - ALTER WORKLOAD CLASS "WLC_TIMEOUT_REPLICA" ENABLE; + ALTER WORKLOAD CLASS "WLC_TIMEOUT_SOURCE" ENABLE; + ALTER WORKLOAD CLASS "WLC_TIMEOUT_REPLICA" ENABLE; - SELECT * FROM WORKLOAD_CLASSES; - SELECT * FROM WORKLOAD_MAPPINGS; - ``` + SELECT * FROM WORKLOAD_CLASSES; + SELECT * FROM WORKLOAD_MAPPINGS; + ``` 2. Now that the workload classes have been created and mapped, try them out by executing the SQL below. - ```SQL - CREATE OR REPLACE PROCEDURE SLOW_PROCEDURE(IN WAIT_TIME INTEGER) LANGUAGE SQLSCRIPT READS SQL DATA AS - BEGIN - USING SQLSCRIPT_SYNC AS SYNCLIB; - - DECLARE V_START_TIME TIMESTAMP; - DECLARE V_END_TIME TIMESTAMP; - DECLARE V_DURATION_SEC BIGINT; - - V_START_TIME = CURRENT_TIMESTAMP; - CALL SYNCLIB:SLEEP_SECONDS(WAIT_TIME); --waits for the specified number of seconds - V_END_TIME = CURRENT_TIMESTAMP; - V_DURATION_SEC = SECONDS_BETWEEN(V_START_TIME, V_END_TIME); - SELECT TOP 1 C1, V_DURATION_SEC, STATEMENT_EXECUTION_HOST() FROM DAN.MYTABLE WITH HINT (RESULT_LAG('hana_sr')); - END; - - CALL SLOW_PROCEDURE(1); --succeeds - CALL SLOW_PROCEDURE(3); --fails as the limit is 2 seconds for primary - CALL SLOW_PROCEDURE(3) WITH HINT (RESULT_LAG('hana_sr')); --succeeds - CALL SLOW_PROCEDURE(5) WITH HINT (RESULT_LAG('hana_sr')); --fails as the limit is 4 seconds for the replica - ``` + ```SQL + CREATE OR REPLACE PROCEDURE SLOW_PROCEDURE(IN WAIT_TIME INTEGER) LANGUAGE SQLSCRIPT READS SQL DATA AS + BEGIN + USING SQLSCRIPT_SYNC AS SYNCLIB; + + DECLARE V_START_TIME TIMESTAMP; + DECLARE V_END_TIME TIMESTAMP; + DECLARE V_DURATION_SEC BIGINT; + + V_START_TIME = CURRENT_TIMESTAMP; + CALL SYNCLIB:SLEEP_SECONDS(WAIT_TIME); --waits for the specified number of seconds + V_END_TIME = CURRENT_TIMESTAMP; + V_DURATION_SEC = SECONDS_BETWEEN(V_START_TIME, V_END_TIME); + SELECT TOP 1 C1, V_DURATION_SEC, STATEMENT_EXECUTION_HOST() FROM DAN.MYTABLE WITH HINT (RESULT_LAG('hana_sr')); + END; + + CALL SLOW_PROCEDURE(1); --succeeds + CALL SLOW_PROCEDURE(3); --fails as the limit is 2 seconds for primary + CALL SLOW_PROCEDURE(3) WITH HINT (RESULT_LAG('hana_sr')); --succeeds + CALL SLOW_PROCEDURE(5) WITH HINT (RESULT_LAG('hana_sr')); --fails as the limit is 4 seconds for the replica + ``` ![workload class result](workload-class-results.png) diff --git a/tutorials/hana-clients-trace/hana-clients-trace.md b/tutorials/hana-clients-trace/hana-clients-trace.md index 1bac724b3..f24b597a2 100644 --- a/tutorials/hana-clients-trace/hana-clients-trace.md +++ b/tutorials/hana-clients-trace/hana-clients-trace.md @@ -4,7 +4,7 @@ author_name: Dan van Leeuwen author_profile: https://github.com/danielva auto_validation: true time: 10 -tags: [ tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana] +tags: [tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana] primary_tag: software-product>sap-hana-cloud --- @@ -35,9 +35,9 @@ Trace settings can also be configured using environment variables, or via connec 1. Enter the following command to see the current trace settings: - ```Shell - hdbsqldbc_cons SHOW ALL - ``` + ```Shell + hdbsqldbc_cons SHOW ALL + ``` ![hdbsqldbc_cons SHOW ALL Results](ShowAllResults.png) @@ -45,19 +45,27 @@ Trace settings can also be configured using environment variables, or via connec 2. To enable tracing of SQL statements at the INFO level, to enable tracing of TIMING info, and to specify the trace file location and name, enter the following commands: - ```Shell (Microsoft Windows) - hdbsqldbc_cons TRACE SQL ON LEVEL INFO - hdbsqldbc_cons TRACE TIMING ON - mkdir c:\temp\traces - hdbsqldbc_cons TRACE FILENAME c:\temp\traces\SQLDBC-%p.txt - ``` + [OPTION BEGIN [Windows]] - ```Shell (Linux or Mac) - hdbsqldbc_cons TRACE SQL ON LEVEL INFO - hdbsqldbc_cons TRACE TIMING ON - mkdir -p /tmp/traces - hdbsqldbc_cons TRACE FILENAME /tmp/traces/SQLDBC-%p.txt - ``` + ```Shell + hdbsqldbc_cons TRACE SQL ON LEVEL INFO + hdbsqldbc_cons TRACE TIMING ON + mkdir c:\temp\traces + hdbsqldbc_cons TRACE FILENAME c:\temp\traces\SQLDBC-%p.txt + ``` + + [OPTION END] + + [OPTION BEGIN [Linux and Mac]] + + ```Shell + hdbsqldbc_cons TRACE SQL ON LEVEL INFO + hdbsqldbc_cons TRACE TIMING ON + mkdir -p /tmp/traces + hdbsqldbc_cons TRACE FILENAME /tmp/traces/SQLDBC-%p.txt + ``` + + [OPTION END] The `%p` will be replaced with the process ID of the traced application. Including `%p` in the file name ensures that each process can write its own trace file. @@ -81,9 +89,9 @@ Trace settings can also be configured using environment variables, or via connec To see the current settings run: - ```Shell - hdbsqldbc_cons SHOW ALL - ``` + ```Shell + hdbsqldbc_cons SHOW ALL + ``` ![Trace settings](trace-settings.png) @@ -95,45 +103,53 @@ Trace settings can also be configured using environment variables, or via connec 4. Find and open the generated trace file. Remember to replace #### to match the trace file name you wish to open. - ```Shell (Microsoft Windows) - cd c:\temp\traces - dir SQLDBC*.txt /od - notepad SQLDBC-####.txt - ``` + [OPTION BEGIN [Windows]] - ```Shell (Linux or Mac) - cd /tmp/traces - ls -lt - pico SQLDBC-####.txt - ``` + ```Shell + cd c:\temp\traces + dir SQLDBC*.txt /od + notepad SQLDBC-####.txt + ``` + + [OPTION END] + + [OPTION BEGIN [Linux and Mac]] + + ```Shell + cd /tmp/traces + ls -lt + pico SQLDBC-####.txt + ``` + + [OPTION END] ![Replace process ID](ReplaceProcessID.png) Notice that the trace settings are shown at the top of the file. - ``` - libSQLDBCHDB 2.16.18.1676320318 - SYSTEM: Microsoft Windows / X64 - BUILD AT: 2023-02-13 20:43:00 - BRANCH: unknown - BUILD MODE: rel - APPLICATION: C:\SAP\hdbclient\hdbsql.exe - HOST: W-R90XC65K - OS USER: I234567 - CURRENT DIRECTORY: c:\temp\traces - TRACE FILE NAME: c:\temp\traces\SQLDBC-55652.txt - PROCESS ID: 55652 - TRACE FILE WRAP COUNT: 0 - - --- - Enabled Traces: - - SQL Trace: Level INFO - Distribution Trace: Level INFO - Timing Trace - - --- - ``` + ``` + libSQLDBCHDB 2.16.18.1676320318 + SYSTEM: Microsoft Windows / X64 + BUILD AT: 2023-02-13 20:43:00 + BRANCH: unknown + BUILD MODE: rel + APPLICATION: C:\SAP\hdbclient\hdbsql.exe + HOST: W-R90XC65K + OS USER: I234567 + CURRENT DIRECTORY: c:\temp\traces + TRACE FILE NAME: c:\temp\traces\SQLDBC-55652.txt + PROCESS ID: 55652 + TRACE FILE WRAP COUNT: 0 + + --- + Enabled Traces: + + SQL Trace: Level INFO + Distribution Trace: Level INFO + Timing Trace + + --- + ``` If the trace settings change while tracing is enabled, the Enabled Traces section will appear again in the trace file. @@ -141,17 +157,17 @@ Trace settings can also be configured using environment variables, or via connec 5. Search through the trace file and notice the SQL statements that were executed. - ``` - ::PREPARE SQLCURS_1 2023-04-07 12:46:38.497000 [0x000002540c111af0] - SQL COMMAND: SELECT VERSION FROM SYS.M_DATABASE - ``` + ``` + ::PREPARE SQLCURS_1 2023-04-07 12:46:38.497000 [0x000002540c111af0] + SQL COMMAND: SELECT VERSION FROM SYS.M_DATABASE + ``` 6. To turn off tracing for all categories, run the following command: - ```Shell - hdbsqldbc_cons TRACE OFF - hdbsqldbc_cons SHOW ALL - ``` + ```Shell + hdbsqldbc_cons TRACE OFF + hdbsqldbc_cons SHOW ALL + ``` ### Additional Trace Settings @@ -159,33 +175,33 @@ The following are some additional options for tracing. 1. The FLUSH setting, when turned on, can reduce I/O activity. If you are investigating a crash, it should be turned on to ensure that all the trace information is recorded. - ```Shell - hdbsqldbc_cons TRACE FLUSH ON - ``` + ```Shell + hdbsqldbc_cons TRACE FLUSH ON + ``` 2. Note that tracing should be turned off when not in use, as it does impact performance, memory and disk size. The following are some additional options to limit the trace file size to 100 KB (plus an archive file) and to turn on tracing only when a specific error code occurs. Error code 10 occurs when invalid credentials are used. - ```Shell - hdbsqldbc_cons TRACE SIZE 100K - hdbsqldbc_cons TRACE ONLY ON ERROR 10 - ``` + ```Shell + hdbsqldbc_cons TRACE SIZE 100K + hdbsqldbc_cons TRACE ONLY ON ERROR 10 + ``` 3. Filtering can be used to reduce the size of trace files. Place the following SQL statements into a file named sql.sql to try this out. - ```SQL - SELECT 'tracetestUSER1' FROM DUMMY; - CONNECT USER2 PASSWORD Password2; - SELECT 'tracetestUSER2' FROM DUMMY; - ``` + ```SQL + SELECT 'tracetestUSER1' FROM DUMMY; + CONNECT USER2 PASSWORD Password2; + SELECT 'tracetestUSER2' FROM DUMMY; + ``` Execute the commands below to reset the trace settings, enable SQL trace for USER2, and then to run the above SQL statements which will execute as USER1 and then as USER2. - ```Shell - hdbsqldbc_cons TRACE OFF - hdbsqldbc_cons TRACE SQL ON LEVEL INFO - hdbsqldbc_cons TRACE FILTER SQL USER USER2 - hdbsql -U User1UserKey -I sql.sql - ``` + ```Shell + hdbsqldbc_cons TRACE OFF + hdbsqldbc_cons TRACE SQL ON LEVEL INFO + hdbsqldbc_cons TRACE FILTER SQL USER USER2 + hdbsql -U User1UserKey -I sql.sql + ``` The expected result is that the resulting trace file only traces the query from USER2. @@ -193,29 +209,29 @@ The following are some additional options for tracing. To enable filtering by statement hash, you will need to obtain the MD5 value of the SQL statement. Update the sql.sql file with the following: - ```SQL - SELECT 'tracetestUSER1' FROM DUMMY; - CONNECT USER2 PASSWORD Password2; - SELECT 'tracetestUSER2' FROM DUMMY; - SELECT * FROM HOTELS.CUSTOMER; - ``` - + ```SQL + SELECT 'tracetestUSER1' FROM DUMMY; + CONNECT USER2 PASSWORD Password2; + SELECT 'tracetestUSER2' FROM DUMMY; + SELECT * FROM HOTELS.CUSTOMER; + ``` + To obtain the MD5 value, enter the following command: - ```Shell - echo -n " SELECT * FROM HOTELS.CUSTOMER" | md5sum - ``` + ```Shell + echo -n " SELECT * FROM HOTELS.CUSTOMER" | md5sum + ``` Ensure the SQL statement does not include a trailing semicolon (;) when calculating the MD5 hash. Execute the commands below to reset the trace settings, enable SQL to trace for the hash statement, and then to run the above SQL statements. - ```Shell - hdbsqldbc_cons TRACE OFF - hdbsqldbc_cons TRACE SQL ON LEVEL INFO - hdbsqldbc_cons TRACE FILTER STATEMENT HASH "658d31bfb941b60f99decfbaf7f80b3f" - hdbsql -U User1UserKey -I sql.sql - ``` + ```Shell + hdbsqldbc_cons TRACE OFF + hdbsqldbc_cons TRACE SQL ON LEVEL INFO + hdbsqldbc_cons TRACE FILTER STATEMENT HASH "658d31bfb941b60f99decfbaf7f80b3f" + hdbsql -U User1UserKey -I sql.sql + ``` The expected result is that the resulting trace file only traces the specific SQL statement. @@ -235,54 +251,70 @@ The following are some additional options for tracing. - %a represents the application user - %c represents the connection ID - ```Shell (Windows) - set HDB_SQLDBC_TRACEFILE=c:\temp\traces\SQLDBC-%p.txt - set HDB_SQLDBC_TRACEOPTS=SQL=INFO,FLUSH - ``` + [OPTION BEGIN [Windows]] - ```Shell (Linux or Mac) - export HDB_SQLDBC_TRACEFILE=/tmp/traces/SQLDBC-%p.txt - export HDB_SQLDBC_TRACEOPTS=SQL=INFO,FLUSH - ``` + ```Shell + set HDB_SQLDBC_TRACEFILE=c:\temp\traces\SQLDBC-%p.txt + set HDB_SQLDBC_TRACEOPTS=SQL=INFO,FLUSH + ``` + + [OPTION END] + + [OPTION BEGIN [Linux and Mac]] + + ```Shell + export HDB_SQLDBC_TRACEFILE=/tmp/traces/SQLDBC-%p.txt + export HDB_SQLDBC_TRACEOPTS=SQL=INFO,FLUSH + ``` + + [OPTION END] Trace settings in environment variables take precedence over those set using `hdbsqldbc_cons`. The environment variable values can be seen and removed with the following commands. The first and last commands display what the environment variable is set to. The middle command removes the value of the environment variable. - ```Shell (Windows) - set HDB_SQLDBC_TRACEFILE - set HDB_SQLDBC_TRACEFILE= - set HDB_SQLDBC_TRACEFILE + [OPTION BEGIN [Windows]] - set HDB_SQLDBC_TRACEOPTS - set HDB_SQLDBC_TRACEOPTS= - set HDB_SQLDBC_TRACEOPTS - ``` + ```Shell + set HDB_SQLDBC_TRACEFILE + set HDB_SQLDBC_TRACEFILE= + set HDB_SQLDBC_TRACEFILE - ```Shell (Linux or Mac) - printenv | grep HDB_SQLDBC_TRACE - unset HDB_SQLDBC_TRACEFILE - unset HDB_SQLDBC_TRACEOPTS - printenv | grep HDB_SQLDBC_TRACE - ``` + set HDB_SQLDBC_TRACEOPTS + set HDB_SQLDBC_TRACEOPTS= + set HDB_SQLDBC_TRACEOPTS + ``` - ![Environment variable values](EnvironmentVariable.png) + [OPTION END] + + [OPTION BEGIN [Linux and Mac]] + + ```Shell + printenv | grep HDB_SQLDBC_TRACE + unset HDB_SQLDBC_TRACEFILE + unset HDB_SQLDBC_TRACEOPTS + printenv | grep HDB_SQLDBC_TRACE + ``` + + [OPTION END] + + ![Environment variable values](EnvironmentVariable.png) 5. Trace information can be directed to `stdout` or `stderr`. See below for a few examples. - ```Shell - hdbsql -U User1UserKey -Z traceFile=stdout -Z traceOptions=SQL=ERROR,DEBUG=FATAL,FLUSH=ON "SELECT * FROM HOTELS.CUSTOMER" - ``` + ```Shell + hdbsql -U User1UserKey -Z traceFile=stdout -Z traceOptions=SQL=ERROR,DEBUG=FATAL,FLUSH=ON "SELECT * FROM HOTELS.CUSTOMER" + ``` - ```Shell - set HDB_SQLDBC_TRACEOPTS=SQL=ERROR,DEBUG=FATAL,FLUSH=ON - set HDB_SQLDBC_TRACEFILE=stdout - hdbsql -U User1UserKey "SELECT * FROM HOTELS.CUSTOMER" - set HDB_SQLDBC_TRACEOPTS= - set HDB_SQLDBC_TRACEFILE= - ``` + ```Shell + set HDB_SQLDBC_TRACEOPTS=SQL=ERROR,DEBUG=FATAL,FLUSH=ON + set HDB_SQLDBC_TRACEFILE=stdout + hdbsql -U User1UserKey "SELECT * FROM HOTELS.CUSTOMER" + set HDB_SQLDBC_TRACEOPTS= + set HDB_SQLDBC_TRACEFILE= + ``` - ![Environment variables set using -Z](environment-variables-z.png) + ![Environment variables set using -Z](environment-variables-z.png) It is also possible to set in a Cloud Foundry manifest file or in the SAP BTP Cockpit. @@ -312,85 +344,125 @@ javac -version 1. To show the current JDBC tracing configuration, run the following command: - ```Shell (Windows) - java -jar C:\SAP\hdbclient\ngdbc.jar SHOW - ``` + [OPTION BEGIN [Windows]] - ```Shell (Linux or Mac) - java -jar ~/sap/hdbclient/ngdbc.jar SHOW - ``` + ```Shell + java -jar C:\SAP\hdbclient\ngdbc.jar SHOW + ``` + + [OPTION END] + + [OPTION BEGIN [Linux and Mac]] + + ```Shell + java -jar ~/sap/hdbclient/ngdbc.jar SHOW + ``` + + [OPTION END] Alternatively, the trace settings can be viewed and set using a GUI. - ```Shell (Windows) - java -jar C:\SAP\hdbclient\ngdbc.jar - ``` + [OPTION BEGIN [Windows]] - ```Shell (Linux or Mac) - java -jar ~/sap/hdbclient/ngdbc.jar - ``` + ```Shell + java -jar C:\SAP\hdbclient\ngdbc.jar + ``` + + [OPTION END] + + [OPTION BEGIN [Linux and Mac]] + + ```Shell + java -jar ~/sap/hdbclient/ngdbc.jar + ``` + + [OPTION END] ![JDBC driver GUI](JDBC-Driver-Trace-Config.png) 2. Turn on the tracing for SQL statements using either the GUI or the commands below: - ```Shell (Windows) - java -jar C:\SAP\hdbclient\ngdbc.jar TRACE ON - java -jar C:\SAP\hdbclient\ngdbc.jar TRACE FILENAME C:\temp\traces\jdbctrace - java -jar C:\SAP\hdbclient\ngdbc.jar TRACE API ON - ``` + [OPTION BEGIN [Windows]] - ```Shell (Linux and Mac) - java -jar ~/sap/hdbclient/ngdbc.jar TRACE ON - java -jar ~/sap/hdbclient/ngdbc.jar TRACE FILENAME ~/tmp/traces/jdbctrace - java -jar ~/sap/hdbclient/ngdbc.jar TRACE API ON - ``` + ```Shell + java -jar C:\SAP\hdbclient\ngdbc.jar TRACE ON + java -jar C:\SAP\hdbclient\ngdbc.jar TRACE FILENAME C:\temp\traces\jdbctrace + java -jar C:\SAP\hdbclient\ngdbc.jar TRACE API ON + ``` + + [OPTION END] + + [OPTION BEGIN [Linux and Mac]] + + ```Shell + java -jar ~/sap/hdbclient/ngdbc.jar TRACE ON + java -jar ~/sap/hdbclient/ngdbc.jar TRACE FILENAME ~/tmp/traces/jdbctrace + java -jar ~/sap/hdbclient/ngdbc.jar TRACE API ON + ``` + + [OPTION END] >The different command-line option keywords can be found at [JDBC Tracing and Trace Options](https://help.sap.com/docs/SAP_HANA_CLIENT/f1b440ded6144a54ada97ff95dac7adf/4033f8e603504c0faf305ab77627af03.html). 3. Execute a query which will generate a trace file. - ```Shell (Windows) - java -jar c:\sap\hdbclient\ngdbc.jar -k USER1UserKey -o encrypt=True -o validatecertificate=false -c "SELECT * FROM HOTELS.CUSTOMER" - ``` + [OPTION BEGIN [Windows]] - ```Shell (Linux and Mac) - java -jar ~/sap/hdbclient/ngdbc.jar -k USER1UserKey -o encrypt=True -o validatecertificate=false -c "SELECT * FROM HOTELS.CUSTOMER" - ``` + ```Shell + java -jar c:\sap\hdbclient\ngdbc.jar -k USER1UserKey -o encrypt=True -o validatecertificate=false -c "SELECT * FROM HOTELS.CUSTOMER" + ``` + + [OPTION END] + + [OPTION BEGIN [Linux and Mac]] + + ```Shell + java -jar ~/sap/hdbclient/ngdbc.jar -k USER1UserKey -o encrypt=True -o validatecertificate=false -c "SELECT * FROM HOTELS.CUSTOMER" + ``` + + [OPTION END] 4. Examine the trace file by using the `cat` command (Linux or Mac) or the `type` command on Windows. - ``` -

-   Java version:   11
-   ClassLoader:    jdk.internal.loader.ClassLoaders$AppClassLoader@30946e09
-   Process ID:     47584
-   Driver version: package com.sap.db.jdbc, JDBC, version 4.2, SAP HANA JDBC Driver, SAP SE, 2.16.9-62f3b9598d4106abb5cce5562c88d3abecca5580
-
-   Trace configuration:
-   Levels:                                       API,PACKET,CONNECTIONS,CLEANERS
-   Show plain-text client-side encrypted values: Disabled
-   Show timestamps:                              Disabled
-   Show elapsed times:                           Disabled
-   Trace file size:                              Unlimited
-   Stop on error:                                Disabled
-
-   ...
-
-   com.sap.db.jdbc.HanaConnectionClean@731f8236[ID:202968].createStatement()
-   => com.sap.db.jdbc.HanaStatement@117159c0
-   com.sap.db.jdbc.HanaStatement@117159c0.execute("SELECT * FROM HOTELS.CUSTOMER")
-   ```
+    ```
+    <html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body><PRE><PLAINTEXT>
+    Java version:   11
+    ClassLoader:    jdk.internal.loader.ClassLoaders$AppClassLoader@30946e09
+    Process ID:     47584
+    Driver version: package com.sap.db.jdbc, JDBC, version 4.2, SAP HANA JDBC Driver, SAP SE, 2.16.9-62f3b9598d4106abb5cce5562c88d3abecca5580
+
+    Trace configuration:
+    Levels:                                       API,PACKET,CONNECTIONS,CLEANERS
+    Show plain-text client-side encrypted values: Disabled
+    Show timestamps:                              Disabled
+    Show elapsed times:                           Disabled
+    Trace file size:                              Unlimited
+    Stop on error:                                Disabled
+
+    ...
+
+    com.sap.db.jdbc.HanaConnectionClean@731f8236[ID:202968].createStatement()
+    => com.sap.db.jdbc.HanaStatement@117159c0
+    com.sap.db.jdbc.HanaStatement@117159c0.execute("SELECT * FROM HOTELS.CUSTOMER")
+    ```
 
 5. Tracing information can be sent to `stdout` or `stderr` as shown below.
 
-   ```Shell (Windows)
-   java -jar c:\sap\hdbclient\ngdbc.jar -k User1UserKey -o traceFile=stdout -o traceOptions=CONNECTIONS -c "SELECT * FROM HOTELS.CUSTOMER"
-   ```
+    [OPTION BEGIN [Windows]]
 
-   ```Shell (Linux or Mac)
-   java -jar ~/sap/hdbclient/ngdbc.jar -k USER1UserKey -o traceFile=stdout -o traceOptions=CONNECTIONS -c "SELECT * FROM HOTELS.CUSTOMER"
-   ```
+    ```Shell
+    java -jar c:\sap\hdbclient\ngdbc.jar -k User1UserKey -o traceFile=stdout -o traceOptions=CONNECTIONS -c "SELECT * FROM HOTELS.CUSTOMER"
+    ```
+
+    [OPTION END]
+
+    [OPTION BEGIN [Linux and Mac]]
+
+    ```Shell
+    java -jar ~/sap/hdbclient/ngdbc.jar -k USER1UserKey -o traceFile=stdout -o traceOptions=CONNECTIONS -c "SELECT * FROM HOTELS.CUSTOMER"
+    ```
+
+    [OPTION END]
 
 6. Tracing can also be enabled via the connection parameters.  For further details see [Trace a JDBC Connection Using a Connection String](https://help.sap.com/docs/SAP_HANA_CLIENT/f1b440ded6144a54ada97ff95dac7adf/250544c4c9f74855862a40a78d4ee3b5.html).
 
diff --git a/tutorials/hana-clients-x509/hana-clients-x509.md b/tutorials/hana-clients-x509/hana-clients-x509.md
index b96da77c6..bd4fe781e 100644
--- a/tutorials/hana-clients-x509/hana-clients-x509.md
+++ b/tutorials/hana-clients-x509/hana-clients-x509.md
@@ -4,7 +4,7 @@ author_name: Dan van Leeuwen
 author_profile: https://github.com/danielva
 auto_validation: true
 time: 15
-tags: [ software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana, programming-tool>sql,tutorial>intermediate, topic>security]
+tags: [software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product>sap-hana, programming-tool>sql,tutorial>intermediate, topic>security]
 primary_tag: software-product>sap-hana-cloud
 ---
 
@@ -52,9 +52,9 @@ As a first step, we will ensure that basic connectivity is working with a user n
 
 1. Check the version of SAP HANA Client on your machine and ensure it is a recent release.  
 
-   ```Shell
-   hdbsql -v 
-   ```
+    ```Shell
+    hdbsql -v 
+    ```
 
     ![hdbsql version](hdbsql-version.png)
 
@@ -64,21 +64,29 @@ As a first step, we will ensure that basic connectivity is working with a user n
 
     Execute the following SQL to create a user to attempt to connect with.
 
-   ```SQL
-   CREATE USER TESTUSER PASSWORD Password1 NO FORCE_FIRST_PASSWORD_CHANGE SET USERGROUP DEFAULT;
-   ```
+    ```SQL
+    CREATE USER TESTUSER PASSWORD Password1 NO FORCE_FIRST_PASSWORD_CHANGE SET USERGROUP DEFAULT;
+    ```
 
     ![Create a test user in the SAP HANA database explorer](test-user-sqlcons.png)
 
 3. Attempt to connect with hdbsql using basic authentication. Be sure to replace the SQL endpoint value with the SQL endpoint of your HANA instance.
 
-   ```Shell (Microsoft Windows)
-   hdbsql -j -A -sslprovider mscrypto -u TESTUSER -p Password1 -Z traceFile=stdout -Z traceOptions=debug=warning,flush=on -n xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.hana.trial-us10.hanacloud.ondemand.com:443 "SELECT CURRENT_USER, CURRENT_SCHEMA FROM DUMMY;"
-   ```
+    [OPTION BEGIN [Windows]]
 
-   ```Shell (Linux or Mac)
-   hdbsql -j -A -sslprovider openssl -u TESTUSER -p Password1 -Z traceFile=stdout -Z traceOptions=debug=warning,flush=on -n xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.hana.trial-us10.hanacloud.ondemand.com:443 "SELECT CURRENT_USER, CURRENT_SCHEMA FROM DUMMY;"
-   ```
+    ```Shell
+    hdbsql -j -A -sslprovider mscrypto -u TESTUSER -p Password1 -Z traceFile=stdout -Z traceOptions=debug=warning,flush=on -n xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.hana.trial-us10.hanacloud.ondemand.com:443 "SELECT CURRENT_USER, CURRENT_SCHEMA FROM DUMMY;"
+    ```
+
+    [OPTION END]
+
+    [OPTION BEGIN [Linux and Mac]]
+
+    ```Shell
+    hdbsql -j -A -sslprovider openssl -u TESTUSER -p Password1 -Z traceFile=stdout -Z traceOptions=debug=warning,flush=on -n xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.hana.trial-us10.hanacloud.ondemand.com:443 "SELECT CURRENT_USER, CURRENT_SCHEMA FROM DUMMY;"
+    ```
+
+    [OPTION END]
 
     ![successful connection with user and password authentication](test-user-hdbsql.png)
 
@@ -88,9 +96,9 @@ The following steps were performed on Linux (using WSL) with an installation of
 
 1. Verify that OpenSSL is installed.
 
-   ```Shell
-   openssl version
-   ```
+    ```Shell
+    openssl version
+    ```
 
     If OpenSSL is installed a value such as "OpenSSL 3.0.8 7 Feb 2023" will be shown.  
 
@@ -100,13 +108,13 @@ The following steps were performed on Linux (using WSL) with an installation of
 
 2. Create a folder where the generated certificates will be stored.  Create a private key and public certificate for a self-signed certificate authority.
 
-   ```Shell
-   mkdir ~/certs
-   cd ~/certs
-   openssl genrsa -out demorootca.key 4096
-   openssl req -x509 -new -nodes -key demorootca.key -sha256 -days 365 -subj "/CN=DEMO_ROOT_CERT_AUTH/ST=ON" -out demorootca.crt
-   ls -al
-   ```
+    ```Shell
+    mkdir ~/certs
+    cd ~/certs
+    openssl genrsa -out demorootca.key 4096
+    openssl req -x509 -new -nodes -key demorootca.key -sha256 -days 365 -subj "/CN=DEMO_ROOT_CERT_AUTH/ST=ON" -out demorootca.crt
+    ls -al
+    ```
 
     ![create a certificate authority](rootca.png)
 
@@ -116,36 +124,36 @@ The following steps were performed on Linux (using WSL) with an installation of
 
 1. Create a private user key and a certificate signing request.
 
-   ```Shell
-   openssl genrsa -out test_x509_user.key 2048
-   openssl req -new -nodes -key test_x509_user.key -out test_x509_user.csr -subj "/CN=TESTX509"
-   ls -al
-   ```
+    ```Shell
+    openssl genrsa -out test_x509_user.key 2048
+    openssl req -new -nodes -key test_x509_user.key -out test_x509_user.csr -subj "/CN=TESTX509"
+    ls -al
+    ```
 
     ![create client certificate](user-csr.png)
 
 2. Create a client certificate that has been signed by the certificate authority.
 
-   ```Shell
-   openssl x509 -req -in test_x509_user.csr -CA demorootca.crt -CAkey demorootca.key -CAcreateserial -days 31 -out test_x509_user.crt
-   ls -al
-   ```
+    ```Shell
+    openssl x509 -req -in test_x509_user.csr -CA demorootca.crt -CAkey demorootca.key -CAcreateserial -days 31 -out test_x509_user.crt
+    ls -al
+    ```
 
     ![create client certificate](client-cert.png)
 
 3. Perform the following steps in your selected environment to verify that the user certificate has been signed by the certificate authority.
 
-   ```Shell
-   openssl verify -CAfile demorootca.crt test_x509_user.crt
-   ```
+    ```Shell
+    openssl verify -CAfile demorootca.crt test_x509_user.crt
+    ```
 
 4. Display the client certificate using openssl and by examining the certificate once imported into SAP HANA.
 
     Use openSSL to display the certificate.
-    
-   ```Shell
-   openssl x509 -text -noout -in test_x509_user.crt
-   ```
+
+    ```Shell
+    openssl x509 -text -noout -in test_x509_user.crt
+    ```
 
     ![client certificate](display-cert.png)
 
@@ -153,22 +161,22 @@ The following steps were performed on Linux (using WSL) with an installation of
 
     View the contents of the certificate using the following command:
 
-   ```Shell
-   cat test_x509_user.crt
-   ```
+    ```Shell
+    cat test_x509_user.crt
+    ```
 
     Open the SQL Console for your SAP HANA database instance. Execute the below SQL to import and view the certificate.  Before executing, update the FROM content to reflect your certificate.
 
-   ```SQL
-   CREATE CERTIFICATE X509_USER_CERT FROM '-----BEGIN CERTIFICATE-----
-   MIIDuDCCAaACFD8uRrS2MgGqakcJZ6bPOyl7f5NfMA0GCSqGSIb3DQEBCwUAMB4x
-   ...
-   eHDFB5AyicWtbXoqVohrcv1QIG9S5eFP3ub5ijruUatC0UTVRyWMLjZtvDY=
-   -----END CERTIFICATE-----';
-   SELECT CERTIFICATE_NAME, SUBJECT_DISTINGUISHED_NAME, ISSUER_DISTINGUISHED_NAME, ISSUER_COMMON_NAME
-       FROM CERTIFICATES WHERE CERTIFICATE_NAME='X509_USER_CERT';
-   --DROP CERTIFICATE X509_USER_CERT;  --This cert is only imported so we can view it.  It can be dropped at any time 
-   ```
+    ```SQL
+    CREATE CERTIFICATE X509_USER_CERT FROM '-----BEGIN CERTIFICATE-----
+    MIIDuDCCAaACFD8uRrS2MgGqakcJZ6bPOyl7f5NfMA0GCSqGSIb3DQEBCwUAMB4x
+    ...
+    eHDFB5AyicWtbXoqVohrcv1QIG9S5eFP3ub5ijruUatC0UTVRyWMLjZtvDY=
+    -----END CERTIFICATE-----';
+    SELECT CERTIFICATE_NAME, SUBJECT_DISTINGUISHED_NAME, ISSUER_DISTINGUISHED_NAME, ISSUER_COMMON_NAME
+        FROM CERTIFICATES WHERE CERTIFICATE_NAME='X509_USER_CERT';
+    --DROP CERTIFICATE X509_USER_CERT;  --This cert is only imported so we can view it.  It can be dropped at any time 
+    ```
 
     ![View client certificate in the SAP HCC SQL console](view-client-cert-sqlcons.png)
 
@@ -180,19 +188,19 @@ The details of the client certificate needed for authentication will be stored i
 
 1. Create a PEM file for use with OpenSSL.
 
-   ```Command Prompt
-   cat test_x509_user.key test_x509_user.crt demorootca.crt > test_x509_user.pem
-   ```
+    ```Command Prompt
+    cat test_x509_user.key test_x509_user.crt demorootca.crt > test_x509_user.pem
+    ```
 
-   ```Powershell
-   Get-Content test_x509_user.key, test_x509_user.crt, demorootca.crt | Set-Content test_x509_user.pem
-   ```
+    ```Powershell
+    Get-Content test_x509_user.key, test_x509_user.crt, demorootca.crt | Set-Content test_x509_user.pem
+    ```
 
 2. Optionally create a PSE for use with SAP CommonCryptoLib.  sapgenpse is included in an install of the SAP HANA Client that is downloaded from the SAP Software Center.  
 
-   ```Shell
-   sapgenpse import_p8 -p ~/certs/test_x509_user.pse -x "" ~/certs/test_x509_user.pem
-   ```
+    ```Shell
+    sapgenpse import_p8 -p ~/certs/test_x509_user.pse -x "" ~/certs/test_x509_user.pem
+    ```
 
     Additional details on sapgenpse can be found by entering `sapgenpse -h or sapgenpse import_p8 -h`.
 
@@ -200,18 +208,18 @@ The details of the client certificate needed for authentication will be stored i
 
 1. View the contents of the `demorootca.crt` file.
 
-   ```Shell
-   cat demorootca.crt
-   ```
+    ```Shell
+    cat demorootca.crt
+    ```
 
 2. In the SAP HANA Cloud Central SQL console, execute the following SQL to create a certificate from the self-signed certificate authority.  
 
-   ```SQL
-   CREATE CERTIFICATE DEMOROOTCA_CERT FROM '';  --Past the contents of the demorootca.crt file
-   SELECT CERTIFICATE_NAME, SUBJECT_DISTINGUISHED_NAME, ISSUER_DISTINGUISHED_NAME, ISSUER_COMMON_NAME
-       FROM CERTIFICATES WHERE CERTIFICATE_NAME = 'DEMOROOTCA_CERT';
-   --It may also be of interest to import the test_x509_user.crt file and view its contents with in the same way as shown above.
-   ```
+    ```SQL
+    CREATE CERTIFICATE DEMOROOTCA_CERT FROM '';  --Past the contents of the demorootca.crt file
+    SELECT CERTIFICATE_NAME, SUBJECT_DISTINGUISHED_NAME, ISSUER_DISTINGUISHED_NAME, ISSUER_COMMON_NAME
+        FROM CERTIFICATES WHERE CERTIFICATE_NAME = 'DEMOROOTCA_CERT';
+    --It may also be of interest to import the test_x509_user.crt file and view its contents with in the same way as shown above.
+    ```
 
     ![details of the DEMOROOTCA_CERT](demorootca-query-sqlcons.png)
 
@@ -221,16 +229,16 @@ The details of the client certificate needed for authentication will be stored i
 
 1. Execute the following queries in the SQL console.  
 
-   ```SQL
-   CREATE X509 PROVIDER DEMO_X509_PROVIDER WITH ISSUER 'SP=ON, CN=DEMO_ROOT_CERT_AUTH';
-   SELECT * FROM X509_PROVIDERS;
-   CREATE PSE X509_PSE;
-   SELECT * FROM PSES;
-   ALTER PSE X509_PSE ADD CERTIFICATE DEMOROOTCA_CERT;
-   SELECT * FROM PSE_CERTIFICATES;
-   SET PSE X509_PSE PURPOSE X509 FOR PROVIDER DEMO_X509_PROVIDER;
-   SELECT * FROM PSES;
-   ```
+    ```SQL
+    CREATE X509 PROVIDER DEMO_X509_PROVIDER WITH ISSUER 'SP=ON, CN=DEMO_ROOT_CERT_AUTH';
+    SELECT * FROM X509_PROVIDERS;
+    CREATE PSE X509_PSE;
+    SELECT * FROM PSES;
+    ALTER PSE X509_PSE ADD CERTIFICATE DEMOROOTCA_CERT;
+    SELECT * FROM PSE_CERTIFICATES;
+    SET PSE X509_PSE PURPOSE X509 FOR PROVIDER DEMO_X509_PROVIDER;
+    SELECT * FROM PSES;
+    ```
 
     ![create a provider and pse](provider-and-pse.png)
 
@@ -273,9 +281,9 @@ Further details can be found at [CREATE USER Statement](https://help.sap.com/doc
 
 1. Use hdbsql to connect to a HANA instance using a certificate.  Adjust the location of the test_x509_user.pem and the host and port values accordingly.
 
-   ```Shell (Linux or Mac)
-   hdbsql -j -A -sslprovider openssl -Z authenticationMethods=x509 -Z authenticationX509=test_x509_user.pem -Z traceFile=stdout -Z traceOptions=debug=error,flush=on -n xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.hana.trial-us10.hanacloud.ondemand.com:443  "SELECT CURRENT_USER, CURRENT_SCHEMA FROM DUMMY;"
-   ```
+    ```Shell
+    hdbsql -j -A -sslprovider openssl -Z authenticationMethods=x509 -Z authenticationX509=test_x509_user.pem -Z traceFile=stdout -Z traceOptions=debug=error,flush=on -n xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.hana.trial-us10.hanacloud.ondemand.com:443  "SELECT CURRENT_USER, CURRENT_SCHEMA FROM DUMMY;"
+    ```
 
     ![successful connection using the client certificate](openSSL-linux.png)
 
@@ -298,9 +306,9 @@ Further details can be found at [CREATE USER Statement](https://help.sap.com/doc
 
     Notice that the changes are to the parameters sslprovider and the pse is used rather than the pem for the authenticationX509 parameter. Adjust the location of the test_x509_user.pse if necessary and be sure to replace the placeholder SQL endpoint with the SQL endpoint of your instance.
 
-   ```Shell
-   hdbsql -j -A -sslprovider commoncrypto -Z authenticationMethods=x509 -Z authenticationX509=~/certs/test_x509_user.pse -Z traceFile=stdout -Z traceOptions=debug=error,flush=on -n xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.hana.trial-us10.hanacloud.ondemand.com:443  "SELECT CURRENT_USER, CURRENT_SCHEMA FROM DUMMY;"
-   ```
+    ```Shell
+    hdbsql -j -A -sslprovider commoncrypto -Z authenticationMethods=x509 -Z authenticationX509=~/certs/test_x509_user.pse -Z traceFile=stdout -Z traceOptions=debug=error,flush=on -n xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.hana.trial-us10.hanacloud.ondemand.com:443  "SELECT CURRENT_USER, CURRENT_SCHEMA FROM DUMMY;"
+    ```
 
     >When using macOS, you may need to specify the full path to the PSE file instead of using ~.
 
@@ -310,68 +318,84 @@ Further details can be found at [CREATE USER Statement](https://help.sap.com/doc
 
 1. Create a folder named `nodeX509OpenSSL` and enter the newly created directory.
 
-   ```Shell (Microsoft Windows)
-   mkdir %HOMEPATH%\HANAClientsTutorial\nodeX509OpenSSL
-   cd %HOMEPATH%\HANAClientsTutorial\nodeX509OpenSSL
-   ```
+    [OPTION BEGIN [Windows]]
+
+    ```Shell
+    mkdir %HOMEPATH%\HANAClientsTutorial\nodeX509OpenSSL
+    cd %HOMEPATH%\HANAClientsTutorial\nodeX509OpenSSL
+    ```
+
+    [OPTION END]
+
+    [OPTION BEGIN [Linux and Mac]]
+
+    ```Shell
+    mkdir -p $HOME/HANAClientsTutorial/nodeX509OpenSSL
+    cd $HOME/HANAClientsTutorial/nodeX509OpenSSL
+    ```
 
-   ```Shell (Linux or Mac)
-   mkdir -p $HOME/HANAClientsTutorial/nodeX509OpenSSL
-   cd $HOME/HANAClientsTutorial/nodeX509OpenSSL
-   ```
+    [OPTION END]
 
 2. Initialize the project and install the `hana-client` driver from NPM.
 
-   ```Shell
-   npm init -y
-   npm install @sap/hana-client
-   ```
+    ```Shell
+    npm init -y
+    npm install @sap/hana-client
+    ```
 
 3. Open a file named `nodeQuery.js` in an editor.
 
     Substitute `pico` or notepad below for your preferred text editor.  
 
-   ```Shell (Microsoft Windows)
-   notepad nodeQuery.js
-   ```
+    [OPTION BEGIN [Windows]]
 
-   ```Shell (Linux or Mac)
-   pico nodeQuery.js
-   ```
+    ```Shell
+    notepad nodeQuery.js
+    ```
+
+    [OPTION END]
+
+    [OPTION BEGIN [Linux and Mac]]
+
+    ```Shell
+    pico nodeQuery.js
+    ```
+
+    [OPTION END]
 
 4. Add the code below to `nodeQuery.js`.  
 
-   ```JavaScript
-   'use strict';
-   var util = require('util');
-   var hana = require('@sap/hana-client');
+    ```JavaScript
+    'use strict';
+    var util = require('util');
+    var hana = require('@sap/hana-client');
 
-   var connOptions = {
-       //Option 1, retrieve the connection parameters from the hdbuserstore
-       serverNode: '@X509UserKey',  //host, port, authenticationMethod, and pem retrieved from hdbuserstore
+    var connOptions = {
+        //Option 1, retrieve the connection parameters from the hdbuserstore
+        serverNode: '@X509UserKey',  //host, port, authenticationMethod, and pem retrieved from hdbuserstore
 
-       //Option 2, specify the connection parameters rather than use the values from a key
-       //serverNode: 'host:port',
-       //authenticationX509: '~/certs/test_x509_user.pem', //.pem if using OpenSSL and .pse  if using commoncrypto
-       //authenticationX509: 'C:\\Users\\xxx\\certs\\test_x509_user.pse',  //Microsoft Windows
+        //Option 2, specify the connection parameters rather than use the values from a key
+        //serverNode: 'host:port',
+        //authenticationX509: '~/certs/test_x509_user.pem', //.pem if using OpenSSL and .pse  if using commoncrypto
+        //authenticationX509: 'C:\\Users\\xxx\\certs\\test_x509_user.pse',  //Microsoft Windows
 
 
-       //sslValidateCertificate: 'false',  //Must be set to false when connecting to an on-premise instance that uses a self-signed certificate.
-       //traceFile: 'stdout',
-       //traceOptions: 'debug=error,flush=on',
-       sslCryptoProvider: 'openssl',  //openssl or commoncrypto
-       authenticationMethods: 'x509'
-   };
+        //sslValidateCertificate: 'false',  //Must be set to false when connecting to an on-premise instance that uses a self-signed certificate.
+        //traceFile: 'stdout',
+        //traceOptions: 'debug=error,flush=on',
+        sslCryptoProvider: 'openssl',  //openssl or commoncrypto
+        authenticationMethods: 'x509'
+    };
 
-   var connection = hana.createConnection();
+    var connection = hana.createConnection();
 
-   connection.connect(connOptions);
+    connection.connect(connOptions);
 
-   var sql = 'select CURRENT_USER FROM DUMMY;';
-   var result = connection.exec(sql);
-   console.log(util.inspect(result, { colors: false }));
-   connection.disconnect();
-   ```
+    var sql = 'select CURRENT_USER FROM DUMMY;';
+    var result = connection.exec(sql);
+    console.log(util.inspect(result, { colors: false }));
+    connection.disconnect();
+    ```
 
     >If you are using commoncrypto, be sure to replace the contents of `sslCryptoProvider` with `commoncrypto`.  
 
@@ -385,9 +409,9 @@ Further details can be found at [CREATE USER Statement](https://help.sap.com/doc
 
 5. Run the app 
 
-   ```Shell
-   node nodeQuery.js
-   ```
+    ```Shell
+    node nodeQuery.js
+    ```
 
     ![Running nodeQuery.js](node-query.png)
 
@@ -406,16 +430,24 @@ DROP X509 PROVIDER DEMO_X509_PROVIDER;
 DROP USER TESTUSER;
 ```
 
-```Shell (Microsoft Windows)
+[OPTION BEGIN [Windows]]
+
+```Shell
 cd %HOMEPATH%/certs
 del * /Q
 ```
 
-```Shell (Linux or Mac)
+[OPTION END]
+
+[OPTION BEGIN [Linux and Mac]]
+
+```Shell
 cd ~/certs
 rm *
 ```
 
+[OPTION END]
+
 ### Knowledge check
 
 Congratulations! You have now used an X.509 client certificate when connecting to an SAP HANA Cloud database.
diff --git a/tutorials/hana-cloud-sqltools-import-export/hana-cloud-sqltools-import-export.md b/tutorials/hana-cloud-sqltools-import-export/hana-cloud-sqltools-import-export.md
index b618019c1..883bc4906 100644
--- a/tutorials/hana-cloud-sqltools-import-export/hana-cloud-sqltools-import-export.md
+++ b/tutorials/hana-cloud-sqltools-import-export/hana-cloud-sqltools-import-export.md
@@ -3,7 +3,7 @@ author_name: Michelle Wang
 author_profile: https://github.com/MichelleWangSAP
 auto_validation: true
 time: 20
-tags: [ tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product-function>sap-hana-cloud--data-lake]
+tags: [tutorial>beginner, software-product>sap-hana-cloud, software-product-function>sap-hana-cloud--sap-hana-database, software-product-function>sap-hana-cloud--data-lake]
 primary_tag: software-product>sap-hana-cloud
 parser: v2
 ---
@@ -69,9 +69,9 @@ The following steps demonstrate how to export and import data from the MAINTENAN
 
     After completing the wizard, the contents of the MAINTENANCE table should be the same as before the delete statement was executed. Run the following SQL statement to confirm.
 
-   ```SQL
-   SELECT * FROM HOTELS.MAINTENANCE;
-   ```
+    ```SQL
+    SELECT * FROM HOTELS.MAINTENANCE;
+    ```
 
     ![Maintenance table](maintenance-table.png)
 
@@ -409,7 +409,7 @@ To try these out, follow the steps below.
 
     Choose **Local Computer** for the export location and provide a name for the archive. 
 
-    ![Target settings]](target.png)
+    ![Target settings](target.png)
 
     Next, select an export format such as CSV, and click **Export**.