go to post Evgeny Shvarov · Jun 30 Thank you, @Ashok Kumar T ! I went to submit an idea to fix this, and found your's one :) Voted.
go to post Evgeny Shvarov · Jun 29 Yes, thank you, AI. But I want it not to care about the case completely.
go to post Evgeny Shvarov · Jun 27 A yet another workaround for non-obvious caveat of using %JSON.Adapter and JSON transport around persistent data is a necessity to add an ID related property to your persistent class, like PersonId in this case: Property PersonId As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ]; This will allow to export ID of a record in DB automatically. Same when you do updates with records, you need to remove this PersonId JSON from an update request, .e.g like this: set personDynObj= {}.%FromJSON(person.Read()) do personDynObj.%Remove("PersonId") // Remove PersonId if it exists, as it is calculated set sc = personObj.%JSONImport(personDynObj) set sc = personObj.%Save()
go to post Evgeny Shvarov · Jun 27 The simplest way to programmatically create a database in IRIS is: do $SYSTEM.SQL.Execute("CREATE DATABASE MYDB")
go to post Evgeny Shvarov · Jun 26 And 3 parameters for the spec class that help: HandleCorsRequest - it is most likely CORS will be needed, applicaton/json to support JSON content and ExposeServerExceptions for debug reasons: Class shvarov.person.spec Extends %REST.Spec [ ProcedureBlock ] { Parameter HandleCorsRequest = 1; Parameter CONTENTTYPE = "application/json"; Parameter ExposeServerExceptions = 1; ...
go to post Evgeny Shvarov · Jun 26 also I always add the same _spec GET endpoint to let swagger have a working specification in docker - the default one doesn't work in docker as IRIS default spec one overrides the host variable to one, that doesn't work. ClassMethod GetSpec() As %DynamicObject { set specname=$p(..%ClassName(1),".impl") Set spec = {}.%FromJSON(##class(%Dictionary.CompiledXData).%OpenId(specname_".spec||OpenAPI").Data) Set url = $Select(%request.Secure:"https",1:"http") _ "://"_$Get(%request.CgiEnvs("SERVER_NAME")) _ ":" _ $Get(%request.CgiEnvs("SERVER_PORT")) _ %request.Application Set spec.servers = [{"url" : (url)}] Quit spec }
go to post Evgeny Shvarov · Jun 26 Thanks @Dan Pasco. This is what I used in the example class. Yes, it's great that we have it now in IRIS.
go to post Evgeny Shvarov · Jun 26 @Ben Spead it's great you mentioned %OnAddToSaveSet() triggers - how do you manage cases when records were changed by CREATE/UPDATE SQL query? These triggers not fire in this case, right?
go to post Evgeny Shvarov · Jun 24 Just've published the shvarov-persistent package once installed byUSER>zpm "install shvarov-persistent" will add shvarov.persistent.base class which can be used as an ancestor after %Persistent, like: Class yourclass Extends (%Persistent, shvarov.persistent.base) , which will add two properties: Property CreatedAt As %TimeStamp [ InitialExpression = {$ZDT($H, 3)} ]; Property LastUpdate As %TimeStamp [ SqlComputeCode = {set {*}=$ZDATETIME($HOROLOG,3)}, SqlComputed, SqlComputeOnChange = (%%INSERT, %%UPDATE) ];
go to post Evgeny Shvarov · Jun 24 Hi @Luis Petkovicz! Consider to try csvgen also? it will be: USER>zpm "install csvgen" to install the package, and here is the usage: USER>do ##class(community.csvgen).Generate("/folder/filename.csv") to generate class and import the data into it from an arbitrary csv.
go to post Evgeny Shvarov · Jun 23 Also this could be a typical copy-paste for a REST API app created in a module.xml in a <module> section: <CSPApplication Url="/travel/api" PasswordAuthEnabled="0" UnauthenticatedEnabled="1" DispatchClass="shvarov.travel.disp" MatchRoles=":{$dbrole}" Recurse="1" UseCookies="2" CookiePath="/travel/api" /> where /travel/api is the app name, and shvarov.travel.disp - a generated class vs the swagger spec file and shvarov.travel.spec class.
go to post Evgeny Shvarov · Jun 23 Another useful comment: while generating swagger spec ask GPT to provide meaningful OperationId for every endpoint, otherwise the generated impl class will come with generated names for implementation methods like that:
go to post Evgeny Shvarov · Jun 23 I think it is a good use-case for embedded python. I asked gpt and it suggested the following python code: from datetime import datetime from zoneinfo import ZoneInfo # Original string input_str = "Thu Jul 03 08:20:00 CEST 2025" # Strip the abbreviation since it's not useful for parsing # Replace it with an IANA timezone # Let's assume "CEST" corresponds to Europe/Paris input_str_cleaned = input_str.replace("CEST", "").strip() # Parse the datetime dt_naive = datetime.strptime(input_str_cleaned, "%a %b %d %H:%M:%S %Y") # Localize to the correct zone dt_aware = dt_naive.replace(tzinfo=ZoneInfo("Europe/Paris")) # Format in ISO format with UTC offset print(dt_aware.isoformat()) # e.g., '2025-07-03T08:20:00+02:00' Also it suggested to make a mapping for CEST/CET: tz_abbreviation_map = { "CEST": "Europe/Paris", "CET": "Europe/Paris", "EDT": "America/New_York", "EST": "America/New_York", "PST": "America/Los_Angeles", # Add more mappings as needed }
go to post Evgeny Shvarov · Jun 22 Thank you, @Andrew Sklyarov ! No %OnSave callback is needed for the CreatedAt property in this case
go to post Evgeny Shvarov · Jun 20 Do we have any new options for collections in DDL? Something like: CREATE TABLE Aricle (tags varchar50[]) ?