This will have the same problem.
- Log in to post comments
This will have the same problem.
I think it is important to remember that Row Level Security typically results in worse performance. It is better to create a VIEW and give your users access to the VIEW instead of going through this exercise.
Arockia,
This sounds like something you might want to discuss with the WRC (which is what I do!). You will need to send over a sample table and some test data showing the problem and we'll be able to sort you out in no time.
Cheers!
Kyle
I'm unsure, exactly, what you're trying to do here. You could write a Stored Procedure that returns the value of a global pretty easily. If you need to run code before connecting via ODBC you can use "init code" set up via the $SYSTEM.SQL.SetServerInitCode() API. I'm not sure exactly what you're looking for, though.
So the problem here was likely that you either didn't have the method as an Expression or you weren't QUITting a value. If you have a method that you intend to use as a Webmethod (SOAP method) then you must return a value. Your options are:
Method AddInteger(Arg1 As %Integer, Arg2 As %Integer) As %Integer [ WebMethod, Codemode=Expression ]
{
Arg1 + Arg2
}or
Method AddInteger(Arg1 As %Integer, Arg2 As %Integer) As %Integer [ WebMethod ]
{
QUIT Arg1 + Arg2
}
I'd guess you weren't quitting out the value.
Wellll technically NULL is a valid value for all datatypes. I think what you want to do is to interrogate the metadata information which you can do like so:
SAMPLES>s stmt=##class(%SQL.Statement).%New()
SAMPLES>w stmt.%Prepare("SELECT ID,Name FROM Sample.Person")
1
SAMPLES>w stmt.%Metadata.%Display()
(You'll get lots of output)Note that you can do this even without running the query! You can look at %SQL.StatementMetadata in the Class Reference for more methods and properties that can help you.
Note 2 - Sean's method is also perfectly valid. The only advantage to mine is that you don't have to run the query.
I agree with Mark. If you do not understand his response and/or if you still have questions, I invite you to open an issue at wrc.intersystems.com and the Support Team will help you get to the bottom of this.
While I'm not entirely sure what you are trying to do here as MLLP is a bit foreign to me, the CSP Gateway is just a module added onto a web server. If you can get the setup you want with a webserver, you can use the CSP Gateway to talk to Caché/Ensemble/HealthShare . What exactly are you trying to accomplish here? What's your goal?
That's fine - dynamic SQL has only a small overhead in comparison to embedded SQL.
If you need free-text search, might I recommend iFind? Quick article here:
https://community.intersystems.com/post/free-text-search-way-search-you…
you do need an iKnow enabled license, but this should work on %Text fields.
If by the 'Web Services testing part' you mean a page like this:
http://localhost:57772/csp/samples/SOAP.Demo.cls
That doesn't even use SOAP, it uses an HTML form submission to run the method directly. What that page does is test the logic of your webservice methods in a simple way, to make sure your desired inputs give the desired outputs. You should use something like SoapUI if you want to more completely test your SOAP methods.
This is not documented because we don't want new development using this kind of storage (which we call "SQL Strorage"). We'd much prefer you to use the standard storage strategy that you get for free when creating classes. If you look at Brendan's 5th (of 3) articles, you'll see a link with the text "Get the Examples here" where you can download some examples (if that works, the link will be here as well).
Again, if you can avoid doing this, I recommend using standard storage.
If you run into any problems or if you have any questions, I strongly suggest you contact the WRC.
How does it connect - via ODBC/JDBC or is there another connection mechanism?
Using the macros is a bad idea. The changes to the JSON, especially in this case, are simple. Any source control system worth its salt is going to be able to make nearly all of the changes for you automatically. As far as I know the only change that can't be caught by find-and-replace is the one requiring COS expressions embedded within JSON to have parentheses. In this case, the new syntax is supported in 2016.1 JSON, so you wouldn't even need to change that. Because of the ease of change, the fact that the change only needs to happen once, and the code obfuscation that occurs when adding macros, I do not think using them is a good idea for anyone planning to use Caché's native JSON implementation.
Edit: It occurs to me that the macros would be useful if you have to switch back and forth between 2016.1 and later versions over and over again, but to do the conversion once is too simple to bother with macros.
Are you using a trigger generator or writing your own code? Can you send the whole trigger definition for review?
There is no such command. I would recommend moving the index global as well. However, if this is not an option then you probably want to do something like:
USER>s sql="select Name from %Dictionary.CompiledClass where system=0 and NOT(Name %Startswith '%') AND SUPER [ 'Persistent'"
USER>s rs=##class(%SQL.Statement).%ExecDirect(,sql)
USER>while rs.%Next() { s sc= $classmethod(rs.%GetData(1),"%BuildIndices") w "Built "_rs.%GetData(1)_" with return code = "_sc,! }Obviously this is kind of hacked together and you'll want to clean it up, but the outline is there. I had to make some assumptions like you don't have any other classes in your application that have 'Persistent' in them. If you do then you'll want (Super [ '%Library.Persistent' OR Super [ '%Persistent'). Since classes are case sensitive this should be fine.
Triggers are fired after data normalization and validation. Do you think you can/should use your own datatypes, overriding the Normalize or LogicalToDisplay/DisplayToLogical functions. If that doesn't make sense you could have a field calculated off of the stored data? There are lots of options here, the best one is going to depend strongly on the goals you have for the project.
These answers are all sufficient. However, perhaps a more natural solution is to make the field of type %Date. Then you can use the SelectMode to determine how the date is represented in a query. For instance, look at the DOB field in Sample.Person (in the SAMPLES) namespace. The storage looks like this:
^Sample.PersonD(1)=$lb(","Waterman,Brenda Z.","437-96-2023",36088,...)
Here we see the ID (1) the Name ("Waterman,Brenda Z.") the SSN (437-96-2023), and the DOB (36088). If you want to see the data you can do the following:
--------------------------------------------------------------
SELECT Name,DOB FROM Sample.Person WHERE ID=1
Name DOB
Waterman,Brenda Z. 36088
--------------------------------------------------------------
If we wanted to see that in a readable format, we can change the selectmode and get:
--------------------------------------------------------------
Name DOB
Waterman,Brenda Z. 1939-10-22
--------------------------------------------------------------
Moreover, you can use this in the WHERE clause very naturally:
--------------------------------------------------------------
SELECT Name,DOB FROM Sample.Person WHERE DOB='1939-10-22'
Name DOB
Waterman,Brenda Z. 1939-10-22
Underman,Jane V. 1939-10-22
Bush,Susan E. 1939-10-22
--------------------------------------------------------------
The way to change the selectmode is going to depend on how you are running your query. All queries that come through xDBC are in ODBC mode, so that's easy. If you are running a dynamic SQL statement you can do:
s stmt.%SelectMode=1
Possible values are:
If you are using embedded SQL, you can use the precompiler directive #SQLCompile select=<value> as outlined here:
http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY…
Eduard is right, you should use GREATEST in this case. CASE statements are kind of sloppy, and while they are fine to use, I like to avoid them in order to keep the query as readable as possible.
More to your other points, you can find a list of valid SQL functions here:
http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY…
Note that all $-functions are not SQL Standard and will only work with Caché (most likely), so if you are interested in database agnosticism then try to use one of the more standard functions. Good luck!
-Kyle
Yup!
DELETE FROM Sample.Person where (ID # 2) = 0 --Deletes all even numbered rows (so you know I'm not cheating and using ID numbers)
select * from (select id,name,ssn from sample.person) where %vid between 11 and 20
%VID is a special variable in Cache SQL (VIEW ID, I think?) which allows you limit your rows without too much trouble. And alternative is the following:
select TOP 10 ID,Name,SSN from Sample.Person where ID NOT IN (SELECT TOP 10 ID FROM Sample.Person)
The first TOP gives you your page size, and the subquery's TOP gives you where to start (in this case, we start at 11, because we're ignoring the first 10). You can dynamically put in the sizes for TOP.
SIMPLEST? %String, definitely. You can even use the ['whatsup@doc.com' syntax to search if you have to. Using List of %String is a messy way to do anything in the relational world.
If you do need to index them later, I'm pretty sure you can use iFind to do this without too much trouble (although you would need a new license, potentially).
Cache 2010.2 does not support Java 7:
http://docs.intersystems.com/cache20102/csp/docbook/DocBook.UI.Page.cls…
You'll need to use an older version of Java or a newer version of Caché.
Note: Java 7 was released in July 2011, so obviously we couldn't support it a year before its release.
P.S. Sorry it took you so long to get an answer! If ever you need something more quickly, please feel free to contact the WRC at support@intersystems.com.
Example!
Class:
------------------------------------------
Class Jiri.RegisteredObject extends %RegisteredObject {
Property p1;
Property p2;
}------------------------------------------
Terminal:
------------------------------------------
SAMPLES>s j=##class(Jiri.RegisteredObject).%New()
SAMPLES>s j.p1="test"
SAMPLES>s j.p2="json"
SAMPLES>w ##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(.stream,j)
1
SAMPLES>w stream.Read()
{
"_class":"Jiri.RegisteredObject",
"p1":"test",
"p2":"json"
}
------------------------------------------
Do your CSP Files show up in the Server Explorer portion of Atelier? Also, what is your Atelier version (Atelier->About Atelier)?
P.S. I think that was the most I've ever written "Atelier" in a short time.
I'm pretty sure you need to return an oref to get this working. Here's one that I was able to get working:
Class Sample.SerialGet Extends %Persistent {
Property Address as Sample.Address [calculated];
Method AddressGet() as Sample.Address {
set a=##class(Sample.Address).%New()
set a.City="Cambridge"
set a.State="MA"
set a.Zip="02142"
set a.Street="1 Memorial Drive"
quit a
}
}Terminal:
SAMPLES>s reader=##class(%XML.Reader).%New()
SAMPLES>w reader.OpenFile("/users/kbaxter/downloads/testopensinglequote.xml")
1
SAMPLES>s x=##class(Sample.SerialGet).%New()
SAMPLES>w x.Address
SAMPLES>w x.Address.Street
1 Memorial Drive
I think the best way to do this would be to write something in COS, write a class query with it, and use that as a Table Valued Function. While there might be a relational way to do this, it seems like it'd be messy.
Caché does NOT support SQL-92 in its full implementation, so please refrain from saying so. Example:
SELECT 3+3*3
Result: 18
Clearly, by not following order of operations we are violating the standard. Moreover, despite not conforming perfectly to SQL-92 we do support plenty of extensions, such as Table-Valued Functions.
That said, Caché does not support WITH in the way you describe. However, you can accomplish the same thing by using subqueries, VIEWs, or multiple queries. You can also JOIN each record with its parent and filter on that. If you give some more information I'd be happy to point you in the right direction.
If you want to investigate the performance of the query you can always open a WRC Case (wrc.intersystems.com :-D).
Otherwise, send out your class definition and query plan and I can take a cursory look at it.
I actually baked a cake to commemorate this occasion, and totally not because I'm fat and wanted cake.
Well, if you want good performance in SQL Queries, you need indexes. What do your tables look like? We can definitely get fast performance on a 50M row table, it might just take some work (which we're happy to help with).
Sure - you can try to merge it off before deleting it:
m ^KMB = ^%sqlcq("NSP","SMPQueryHistory")
And then you have your query history in a different global, which you can reference when needed.