How to define a general property for the entire database - sql

I'm managing a database with sqlite and I want to hold a general property
describing the version of my application. This property will be updated for every database change. Is it possible?

If all you want to do is track an application version, Sqlite has a couple of pragmas for querying and setting integer values that are part of the database file format itself, intended for just such a thing.
APPLICATION_ID: This one is meant to be assigned an application-specific ID number that you can check to make sure the database is one created by your program and not something else.
USER_VERSION: This is probably what you'll want to use. I use it for the same purpose you're describing, incrementing it with every new table or whatever, so that if a database with an older schema version is loaded into a program that uses a newer one, it can then upgrade the database as appropriate.

Is it possible?
Yes and is frequently used.
Android's SQLiteOpenHelper class (which you can subclass to) checks the version passed against the version stored.
If the version passed is higher than the version stored then the method (abstract so has to be overridden) onUpgrade is called.
If the version is lower then the onDowngrade method (not abstract but if not overridden results in an exception).
The value is stored in the user_version (offset 60-63 inclusive, in the database header, the first part of the database file) and is a 32bit signed integer.
It can be read by issuing PRAGMA user_versionand then extracted from the result set as column user_version.
It can be set by issuing PRAGMA user_version = ? (where ? is the number that you want it set to).
The highest value that it can be set to is 2147483647, the lowest is -2147483648 values outside of this range result in 0.
PRAGMA user_version;
As an example :-
PRAGMA user_version = -2147483648;
PRAGMA user_version;
PRAGMA user_version = 2147483647;
PRAGMA user_version;
will result in the two requests to return the user_version (2nd an 4th lines) as per :-
and
The next 4 bytes in the header the application_id could be used in a similar way. It's intended to describe a file type akin to file extension like .doc, .pdf and so on and used when Sqlite is used as an application file format. This value being interrogated by the application which then acts accordingly reading storing and retrieving the data.
It's probably not a frequently used value so could also be used in the same way just with different PRAGMA's. PRAGMA application_id and PRAGMA application_id = ? (again where ? is a 32bit signed integer)
PRAGMA application_id;
SQLite As An Application File Format
SQLite As An Application File Format - Benefits(short version)
Database File Format - The Database Header

Related

Can we set multiple DCM_SpecificCharacterSet while importing records using DICOM?

Currently, I am using the below code to set parameters to retrieve data from PACS.
DcmDataset findParams = DcmDataset();
findParams.putAndInsertString(DCM_QueryRetrieveLevel, "SERIES");
findParams.putAndInsertString(DCM_SpecificCharacterSet, "ISO_IR 192");
However, just wanted to check can we provide support multiple characters set to import data at the same time, Code will look like something below, I am trying to check whether this is possible or not as I dont have the facility to verify the same.
findParams.putAndInsertString(DCM_SpecificCharacterSet, "ISO_IR 192" ,"ISO_IR 100");
I think that what you want to express is that "this Query SCU can accept responses in the following character sets". This is plainly not possible. See a discussion in the DICOM newsgroup for reference. It ends with a proposal to add character set negotiation to the association negotiation. But such a supplement has not been submitted yet, and I am not aware of anyone working on it currently.
The semantics of the attribute Specific Character Set (0008,0005) in the context of the Query Retrieve Service Class:
PS3.4, C.4.1.1.3.1 Request Identifier Structure
Conditionally, the Attribute Specific Character Set (0008,0005). This Attribute shall be included if expanded or replacement character sets may be used in any of the Attributes in the Request Identifier. It shall not be included otherwise
I.e. it describes nothing but the character encoding of your request dataset.
and
C.4.1.1.3.2 Response Identifier Structure
Conditionally, the Attribute Specific Character Set (0008,0005). This Attribute shall be included if expanded or replacement character sets may be used in any of the Attributes in the Response Identifier. It shall not be included otherwise. The C-FIND SCP is not required to return responses in the Specific Character Set requested by the SCU if that character set is not supported by the SCP. The SCP may return responses with a different Specific Character Set.
I.e. you cannot control the character set in which the SCP will send you the responses. Surprising but a matter of fact.
Sending multiple values for the attribute is possible but has different semantics. It means that the request contains characters from different character sets which are switched using Code Extension Techniques as defined in ISO 2022. An illustrative example how this would look like and what it would mean is found in PS3.5, H.3.2
What implementors usually do to avoid character set compatibility issues is configuring "the one and only" character set for a particular installation (=hospital) in a locale configuration that is configured upon system setup. It works pretty well, for e.g. an installation in Russia will very likely support Cyrillic (ISO_IR 144) or UNICODE (ISO_IR 192) or both. In case of "both", you can select the character set that you prefer for configuring your system.

How to change number formatting for Hana SQL query session or connection?

For our customers that use SAPB1 with HanaDB we execute the same query to pull data out (using the ADO.NET interface). Some have their regional system systems that appear to control numerical formatting according to their locale, etc.
Say for example when executing: SELECT RDR1."Quantity" FROM RDR1
For a customer in the USA, RDR1."Quantity" = 2.000000
For a customer in Germany, RDR1."Quantity" = 2,000000 (notice the comma vs decimal)
I assume the actual database storage of the value is the same, it is just the query engine that is applying default system formatting based on the settings that makes the end result formatted one way or another.
Now, using a brute force approach and per column this type of change can be made:
REPLACE(CAST(ROUND(RDR1."Quantity",2) AS DECIMAL(10,2)), ',', '.') AS "Quantityā€¯
to give me "2.00"
However we have many columns like this and we want to make the code usable in all cases vs having multiple instances of the same queries for different regions -- and it just seems there should be a way to tell the query engine to return values as if it were in the USA and ignore default system locale and currency settings.
Question: Is it possible to make a high level setting change instead of per column formatting/casting - either using Hana SQL query code (like a session variable or something) or a connection setting when we establish the ADO.NET connection to HanaDB that will just make the values come out as if they were in the USA?
I haven't found any yet but perhaps it is not so easily found in the documentation how to handle it.
No, there is no HANA setting that would define how the application, SAP Business One in your case, renders the data to the user screen.
For SAP B1 you can find the documentation for setting these user settings here.
These settings include "thousands separator", "separator", "decimal places", and others.
But on HANA DB level, there is no global setting for that.
Also, the REPLACE workaround mentioned turns the input number data into a string, losing all the number semantics (ordering, mathematical operations) and increase the memory requirements for those values.
Rather avoid this technique if possible.
If you want to alter the decimal separator of the program output, just tell it to .NET.
An option is to set the Current Thread's Culture like in this snippet:
using System;
using System.Globalization;
class Program
{
static void Main(string[] args)
{
decimal d = 2021.1002m;
Console.WriteLine("Current Culture is {0}.", System.Threading.Thread.CurrentThread.CurrentCulture.Name);
Console.WriteLine("d = {0}.", d);
System.Threading.Thread.CurrentThread.CurrentCulture =
new CultureInfo("en-US");
Console.WriteLine("Current Culture now is {0}.", System.Threading.Thread.CurrentThread.CurrentCulture.Name);
Console.WriteLine("And d = {0}.", d);
}
}
For me the ouput is:
Current Culture is es-ES.
d = 2021,1002.
Current Culture now is en-US.
And d = 2021.1002.

AS400 RPGLE/free dynamic variables in operations

I'm fairly certain after years of searching that this is not possible, but I'll ask anyway.
The question is whether it's possible to use a dynamic variable in an operation when you don't know the field name. For example, I have a data structure that contains a few hundred fields. The operator selects one of those fields and the program needs to know what data resides in the field from the data structure passed. So we'll say that there are 100 fields, and field50 is what the operator chose to operate on. The program would be passed in the field name (i.e. field50) in the FLDNAM variable. The program would read something like this the normal way:
/free
if field50 = 'XXX'
// do something
endif;
/end-free
The problem is that I would have to code this 100 times for every operation. For example:
/free
if fldnam = 'field1';
// do something
elseif fldnam = 'field2';
// do something
..
elseif fldnam = 'field50';
// do something
endif;
Is there any possible way of performing an operation on a field not yet known? (i.e. IF FLDNAM(pointer data) = 'XXX' then do something)
If the data structure is externally-described and you know what file it comes from, you could use the QUSLFLD API to find out the offset, length, and type of the field in the data structure, and then use substring to get the data and then use other calculations to get the value, depending on the data type.
Simple answer, no.
RPG's simply not designed for that. Few languages are.
You may want to look at scripting languages. Perl for instance, can evaluate on the fly. REXX, which comes installed on the IBM i, has an INTERPRET keyword.
REXX Reference manual

How to identify Drive ID?

The new Google Drive Android API has 2 types of string IDs available, the 'resource' ID and the 'encoded' ID.
'encoded' id from DriveId.encodeToString()
"DriveId:CAESHDBCMW1RVVcyYUZKZmRhakIzMDBVbXMYjAUgssy8yYFRTTNKRU55"
'resource' id from DriveId.getResourceId()
"UW2aFJfdajB3M3JENy00Ums0B1mQ"
In the process I end-up with a string that can contain any one of them (result of some timing issues). My question is:
If I need to 'parse' the string in order to identify the type, is there a characteristic I can rely on? For instance:
'encoded' id will always start with 'DriveId:' substring
'resource' id will have some length limit
can I abuse error return from 'decodeFromString()'?
or should I form (pre-pend) the string container with my own tag? What could be the minimal 'safe' tag (i.e. what will never appear in the beginning of these ids) ?
Please point me in the right direction so I don't have to re-do it with the next release.
I have run into yet another issue that should be mentioned here so others don't waste time falling into the same pit. The 'resourceID' can be ported and will remain unique for the object it identifies, where 'encodedID' has only 'device' scope. Means that you CAN'T transfer 'encodedID' to another device (with the same account) and try to retrieve file/folder with it. So I assume it is unique to a Google Play Services instance.
Please do not rely on any formatting of either ID type. This are subject to change without notice.
If you need to use both, and track the differences between them you should have your own method of doing so within your app.
Really, you should probably always just store the encoded ID since this one is always guaranteed to present, and if it contains a resourceId, its easy to get back out.

Generate random GUID

I want to generate a random UUID like in Java with UUID.randomUUID().
I came up with the function GUID_GENERATE and used it like this
DO 5 TIMES.
CALL FUNCTION 'GUID_CREATE'
IMPORTING
ev_guid_16 = ev_guid_16
ev_guid_22 = ev_guid_22
ev_guid_32 = ev_guid_32.
WRITE: /, ev_guid_16, ev_guid_22, ev_guid_32.
ENDDO.
The result of this program is always the same GUID. I need a new random one at every request.
I want to use it as a primary key in database table. This key will be transmitted via a Web Service to a Java application and user there as identifier, too.
Do you have any ideas how I can generate random UUID/GUID in ABAP?
First of all you are using a function module that is obsolete. The comment at the beginning of the source code states that.
*"----------------------------------------------------------------------
* NOW this function has been replaced, see note 935047 "BINK215094
* 28.6.2006 The function module has been switched to the new UUID methods
* which exist in the class cl_system_uuid
* - due to compatibility reasons we catch the exceptions
* - sy-subrc not touched manually
* (sy-subrc was set in case of an error when calling the former
* 'RFCControl' kernel-call, but it wasn't evaluated and finally
* overwritten when leaving this function)
*"----------------------------------------------------------------------
Please use class CL_SYSTEM_UUID and the following methods:
IF_SYSTEM_UUID_STATIC~CREATE_UUID_X16
IF_SYSTEM_UUID_STATIC~CREATE_UUID_C22
IF_SYSTEM_UUID_STATIC~CREATE_UUID_C26
IF_SYSTEM_UUID_STATIC~CREATE_UUID_C32
Are you absolutely sure the created GUID is always the same? Because this shouldn't be happening. Note that the difference between them can be just one character when you generate them inside a fast loop.