I know I'm late to the game, but a few notes I thought were worth mentioning in the context of the question and the discussion here -

1. Re using $sortbegin/$sortend - if you want to take this approach, there are dedicated methods on all %Persistent objects that do exactly this - %SortBegin() and %SortEnd(). Note you can use this per index (or for all) and you don't have to worry about the name of the global etc. So this should definitely be preferred IMHO.

By the way, if you are interested, you can see that the "behind-the-scenes" of %Populate's Populate() method uses this approach (a little advanced generator code...), as well as %SQLImportMgr's  GenerateImportRoutine() method.

2. I don't know if this is relevant for your case, but also for the benefit of the wider community and other use-cases, when it comes to bulk/batch fast operations, if Java or .Net are relevant, then our XEP (eXtreme Event Processing) framework could be a good option. And there indeed you have control over when to perform the indexing.

3. I know the discussion was geared towards OOP and not SQL (and the SQL %NOINDEX option was mentioned more than once), depending on how the data is arriving, you might want to consider using the latest (SQL-based) LOAD (BULK) DATA capability.

4. Relating back to #2 above, re XEP. Behind the scenes the XEP access uses (in some cases) a server-side %SaveDirect() method. In theory you can use this yourself. Note it does not address the no indexing topic (again you can consider using #1 - %SortBegin() and %SortEnd() for that) but it has some other performance advantages as apposed to a regular %Save() (it also has some limitations...). Note there is quite an amount of "hassle" about "preparing" the data for this method, as it needs to be in the $ListBuild format the class's storage expects (and possibly other data nodes). Therefore it is quite rarely used directly (not via XEP). But if you have high performance needs, it might be worth considering this, and comparing the benefit it could provide you vs. the drawbacks it has.

Hi Ephraim,

There could be several reasons - 2 common ones are database expansion and journal expansion (or both).

Here are some sample good resources to see more about this topic -

Hope this helps.

Working with Yakov on this, we saw that for SCOPE_IDENTITY() to work on the SQL Serve side it needs to be in the same "scope" of the INSERT (for example in the same Stored Procedure), see here for reference.

So what Yakov ended up doing was encapsulating the INSERT and SELECT SCOPE_IDENTITY() into a Stored Procedure which returns the newly inserted Row ID, and call the SP via the Adapter, thus inserting the new record and getting back the new ID.

Ok, Carig, so sorry about the superfluous explanation about the SQL Package to Schema name mapping...

But now I do understand the problem better -

First, as you realized you don't need the asterisk (*), just the name of the schema.

And second you need to use the term SCHEMA in your statement before the schema name, or else we expect a table name (hence the error you got - table ... not found).

So per the example I quoted originally above from the documentation:

GRANT SELECT ON SCHEMA Sample TO Deborah

In your example this would be:

GRANT SELECT ON SCHEMA MyPkg_Messages TO myRole

I just added the word 'SCHEMA' before the schema name.

Hope this will get it to work for you.

Hi Craig,

I'm not 100% sure this is the problem you are seeing (you might be aware of this already) - but worth a try - 

When you define an OO package name (and sub-packages) for your classes, these "project" to SQL Schema names a little differently, so instead of "dots" (.) in your full package name you would have underscores (_) in your schema name.

For example PackageA.PackageB.Class would be PackageA_PackageB.Class - so the schema name would be PackageA_PackageB (and not PackageA.PackageB).

See here for example about this in the Documentation.

Hi Craig,

Perhaps this could help -

From: https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI.Page.cls?KEY=RSQL_grant

You can use SCHEMA schema-name as the object-list value to grant the object-privilege to all of the tables, views, and stored procedures in the named schema, in the current namespace. For example, GRANT SELECT ON SCHEMA Sample TO Deborah grants this user SELECT privilege for all objects in the Sample schema. This includes all objects that will be defined in this schema in the future. You can specify multiple schemas as a comma-separated list; for example, GRANT SELECT ON SCHEMA Sample,Cinema TO Deborah grants SELECT privilege for all objects in both the Sample and the Cinema schemas.

I'm not sure if I fully understand your question Eduard, but the token itself, internally, is built by the original request's Message Header ID (and the Production name; concatenated with a pipe - |)

E.g., from the code (in Ens.Host):

Method GetDeferredResponseToken(pMessageHeader As Ens.MessageHeader) As %String
{
    Quit pMessageHeader.%Id()_"|"_$$$EnsRuntime("Name")
}

ClassMethod SendDeferredResponse(pDeferredResponseToken As %String, pResponse As %Library.Persistent) As %Status
{
    Set tSC=$$$OK
    Try {
        Set tMessageHeaderId=$p(pDeferredResponseToken,"|",1)
        Set tProductionName=$p(pDeferredResponseToken,"|",2)

Note this is of course internal implementation, and I don't think it is documented or supported (i.e. might change in future versions without notice).

Thanks for filling in the picture Michael.
So this seems to fit into the theory I had about the error indicating your SOAP client is not receiving the response it expected.

You can see the server (the SOAP service) you are turning to is running into an internal error (HTTP status 500) and you also have details about the error they ran into "javax.... " and their relevant stack.

I suggest, if it is possible, that you turn to the entity that is behind this service and report to them the error you are getting (makes sense also to share with them what you see in the log that you are sending to them).

And they might be able to help you.

Hi Michael,

It's a little difficult to tell just from the description you provided what the problem exactly is, but my guesstimate would be that it actually is not related to the encoding (UTF8 vs ISO-8859-1) of what you are sending, but something to do with the response you are getting back.

As the error you quoted mentions - "... returned response with unexpected...".

And specifically the error is complaining about the content-type being text/html where it should probably be expected to be (in the case of SOAP) xml.

So it looks like you provided an extract from the SOAP log - but of what was sent (Output) but not what was received back.

Maybe share that part and we'd be able to help a little more.

You can use (inside %SYS) Config.Namespaces:Get().

For example -

%SYS > set status = ##class(Config.Namespaces).Get("USER",.properties)

%SYS > zwrite properties
properties("Globals")="USER"
properties("Library")="CACHELIB"
properties("Routines")="USER"
properties("SysGlobals")="CACHESYS"
properties("SysRoutines")="CACHESYS"
properties("TempGlobals")="CACHETEMP"
%SYS > set dataDatabaseName = properties("Globals")

%SYS > write dataDatabaseName
USER
%SYS > set codeDatabaseName = properties("Routines")

%SYS > write codeDatabaseName
USER

Of course assuming you are coming from other namespace into %SYS, you can have the name of that namespace in a variable, and use that variable instead of "USER" in my example above.

If you want the actual directory/folder of the database you can also then use Config.Databases:Get(), for example:

%SYS > set status = ##class(Config.Databases).Get("USER",.properties)

%SYS > zwrite properties
properties("ClusterMountMode")=0
properties("Directory")="C:\InterSystems\IRIS\mgr\user\"
properties("MountAtStartup")=0
properties("MountRequired")=0
properties("Server")=""
properties("StreamLocation")=""

And if you want directly just the locations of the databases, and not their names, you could use %SYS.Namespace:GetAllNSInfo() (without having to move into %SYS first) as @Julius Kavay mentioned.

For example:

USER > do ##class(%SYS.Namespace).GetAllNSInfo("USER",.info)

USER > zwrite info
info("GlobalDB","Directory")="c:\intersystems\IRIS\mgr\user\"
info("GlobalDB","Mounted")=1
info("GlobalDB","ReadOnly")=0
info("GlobalDB","Resource")="%DB_USER"
info("GlobalDB","Status")=1
info("GlobalDB","System")=""
info("RoutineDB","Directory")="c:\intersystems\IRIS\mgr\user\"
info("RoutineDB","Mounted")=1
info("RoutineDB","ReadOnly")=0
info("RoutineDB","Resource")="%DB_USER"
info("RoutineDB","Status")=1
info("RoutineDB","System")=""