I do have a question, though: Is there any way to use a defined ODBC DSN in the connection string using CacheActiveX?No: Defining a Connection String
- Log in to post comments
I do have a question, though: Is there any way to use a defined ODBC DSN in the connection string using CacheActiveX?No: Defining a Connection String
Do make re-indexing: How to build indices for a class if you add an index after creating records
E.g.:
s fileName="C:\temp\test.txt"
s f=##class(%FileCharacterStream).%New()
s f.Filename=fileName
s f1=##class(%FileCharacterStream).%New()
s f1.Filename=fileName
d f.Write("start ")
d f.CopyFrom(f1)
d f.Write(" end")
d f.SaveStream()
s f="",f1=""Result:
test.txt (Before): bla-bla-bla test.txt (After): start bla-bla-bla end
If you know how to work with ActiveX from MS Excel VBA, then there is no problem.
E.g. (demo.vbs):
Set f = CreateObject("CacheActiveX.Factory")
Set rs = CreateObject("CacheActiveX.ResultSet")
If Not f.IsConnected() Then
f.Connect("cn_iptcp:127.0.0.1[1972]:SAMPLES:_SYSTEM:SYS")
Set rs=f.DynamicSQL("select TOP 3 * from Sample.Person")
rs.Execute()
while rs.Next
WScript.Echo rs.Get("SSN") 'print of field SSN for first three rows from the table Sample.Person
wend
rs.Close()
Set person = f.Static("Sample.Person")
age=person.CurrentAge(45678) 'call of method of class Sample.Person
WScript.Echo age
End If
Indeed, thank you:
Class demo.B Extends %Persistent [ Final ]
{
Parameter MANAGEDEXTENT As INTEGER [ Constraint = "0,1", Flags = ENUM ] = 0;
Parameter READONLY = 1;
Property P2;
Storage Default
{
<Data name="BDefaultData">
<Value name="3">
<Value>P2</Value>
</Value>
</Data>
<DataLocation>^demo.AD</DataLocation>
<DefaultData>BDefaultData</DefaultData>
<IdLocation>^demo.AD</IdLocation>
<IndexLocation>^demo.AI</IndexLocation>
<StreamLocation>^demo.AS</StreamLocation>
<Type>%Library.CacheStorage</Type>
}
}Is there any way to "generate" compatible storage? And why SQLStorage? Why not default CachéStorage, but copy-pasted from Class A?Unfortunately, to use %CacheStorage will not work, since at compile occurs the error:
ERROR #5564: Storage reference: '^demo.AD' used in 'demo.B.cls' is already registered for use by 'demo.A.cls'ERROR #5030: An error occurred while compiling class 'demo.B'
If you only need SQL access, then will be easier to create a view (CREATE VIEW), if need both, then - %CacheSQLStorage, e.g.:
Class demo.A Extends %Persistent
{
Property P1;
Property P2;
ClassMethod Fill()
{
d ..%KillExtent()
f i=1:1:3 {
s t=..%New()
s t.P1="P1_"_i
s t.P2="P2_"_i
d t.%Save()
}
}
Storage Default
{
<Data name="ADefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>P1</Value>
</Value>
<Value name="3">
<Value>P2</Value>
</Value>
</Data>
<DataLocation>^demo.AD</DataLocation>
<DefaultData>ADefaultData</DefaultData>
<IdLocation>^demo.AD</IdLocation>
<IndexLocation>^demo.AI</IndexLocation>
<StreamLocation>^demo.AS</StreamLocation>
<Type>%Library.CacheStorage</Type>
}
}
Class demo.B Extends %Persistent [ Final, StorageStrategy = Default ]
{
Parameter READONLY = 1;
Property P2;
Storage Default
{
<SQLMap name="BDefaultData">
<Data name="P2">
<Piece>3</Piece>
</Data>
<Global>^demo.AD</Global>
<RowIdSpec name="1">
<Expression>{L1}</Expression>
<Field>ID</Field>
</RowIdSpec>
<Subscript name="1">
<Expression>{ID}</Expression>
</Subscript>
<Type>data</Type>
</SQLMap>
<StreamLocation>^demo.AS</StreamLocation>
<Type>%CacheSQLStorage</Type>
}
}Result:
USER>d ##class(demo.A).Fill() USER>d $SYSTEM.SQL.Shell() SQL Command Line Shell ---------------------------------------------------- The command prefix is currently set to: <>. Enter q to quit, ? for help. USER>>select * from demo.A 1. select * from demo.A ID P1 P2 1 P1_1 P2_1 2 P1_2 P2_2 3 P1_3 P2_3 3 Rows(s) Affected statement prepare time(s)/globals/lines/disk: 0.1426s/46110/260143/45ms execute time(s)/globals/lines/disk: 0.0004s/16/809/0ms cached query class: %sqlcq.USER.cls12 --------------------------------------------------------------------------- USER>>select * from demo.B 2. select * from demo.B ID P2 1 P2_1 2 P2_2 3 P2_3 3 Rows(s) Affected statement prepare time(s)/globals/lines/disk: 0.0696s/44550/243602/0ms execute time(s)/globals/lines/disk: 0.0002s/4/619/0ms cached query class: %sqlcq.USER.cls13 --------------------------------------------------------------------------- USER>>quit USER>w ##class(demo.B).%OpenId(3).P2 P2_3
Do not forget about the method signature:
ClassMethod main() As %String
Need not print the number, but return it.
See "predefine the type of an specific piece of a global"
USER>s a=" 1.0", b=" 2.2" w w !,a]]b a=" 1.0" b=" 2.2" 0 USER>s a=$double(1.0), b=$double(2.2) w w !,a]]b a=1 b=2.2000000000000001776 0
Ok, exclusively for fun.
I made some improvements and now my score is 9, but if you try very hard, even - 0!
Who less ? ;)
Here is the code:
Class ITPlanet.Task2 [ Abstract ]
{
Parameter p = {$zwbunpack("㤸㜶㔴㌲")};
ClassMethod main() As %String
{
q ..#p
}
}
Class ITPlanet.Test [ Abstract ]
{
ClassMethod length(
class = {$classname()},
method = "main") As %Integer [ CodeMode = expression ]
{
##class(%Dictionary.MethodDefinition).IDKEYOpen(class, method).Implementation.Size
}
ClassMethod test(makeDeploy = {$$$NO})
{
;do ##class(ITPlanet.Test).test()
set classname="ITPlanet.Task2"
set check=9876543210
do:makeDeploy $system.OBJ.MakeClassDeployed(classname)
set result=$classmethod(classname,"main")
write !,result,!,check,
!,"correct: ",$select(result=check:"yes",1:"no"),
!,"length: ",..length(classname)
}
}USER>do ##class(ITPlanet.Test).test() 9876543210 9876543210 correct: yes length: 9 USER>do ##class(ITPlanet.Test).test(1) 9876543210 9876543210 correct: yes length: 0
main ≠ Main
Only I noticed it?
Rhetorical question - for what?
If for fun, then this is possible.
But I will tell the solution here later.
My result is 21.
It is similar to the variant of Alexander, but only _+"".
You can use the class %ZEN.proxyObject, e.g.:
Class demo.Customer Extends %RegisteredObject
{
Property p1 As %String;
Property p2 As %String;
Property list As %Collection.ListOfDT;
/// d ##class(demo.Customer).Test()
ClassMethod Test()
{
s customer=##class(demo.Customer).%New()
s customer.p1="p1"
s customer.p2="p2"
s customer.list=##class(%ListOfDataTypes).%New()
d customer.list.InsertList($lb(1,"two",,"four"))
s appointment=##class(%ZEN.proxyObject).%New()
s appointment.a1="a1"
s appointment.a2="a2"
s appointment.list=##class(%ListOfDataTypes).%New()
d appointment.list.InsertList($lb(2,3,"test",8))
; Cancellation
s response=##class(%ZEN.proxyObject).%New()
s response.Code="Cancellation"
s response.Info="Info_Cancellation"
w response.Code,":",! d response.%ToJSON(,"2aelow")
d response.%Clear()
; Customer
s response.Code="Customer"
s response.Info=customer
w !!,response.Code,":",! d response.%ToJSON(,"2aelow")
d response.%Clear()
; Appointment
s response.Code="Appointment"
s response.Info=appointment
w !!,response.Code,":",! d response.%ToJSON(,"2aelow")
}
}USER>d ##class(demo.Customer).Test()
Cancellation:
{
"Code":"Cancellation",
"Info":"Info_Cancellation"
}
Customer:
{
"Code":"Customer",
"Info": {
"p1":"p1",
"p2":"p2",
"list":["1","two","","four"]
}
}
Appointment:
{
"Code":"Appointment",
"Info": {
"a1":"a1",
"a2":"a2",
"list":[2,3,"test",8
]
}
}The translation was already done: Localization in Caché DBMS
See still of the source code for the following methods:
I want to say that this question was already asked and there it was given some answer. No more than.
I personally use Studio and will continue to use.
What is ..IsIgnored and ..PathDependencies? You could post a complete example?
Initially the question was about alternative ways of solving the issue (in addition to recursive FileSet and $ZSEARCH).
I just proposed a third method, namely using the capabilities of the OS itself. Maybe someone here didn't know about it.
Which option at end to choose - to solve the developer.
We here vote for the best solution or in general for offered solutions?
If the first, then I'll pass.
And if so?
d ##class(%Net.Remote.Utility).RunCommandViaZF($$$FormatText("dir /A-D /B /S %1",$$$quote("C:\InterSystems\Atelier")),.tFileName,,,$$$NO)
s f=##class(%Stream.FileCharacter).%New()
s f.Filename=tFileName
while('f.AtEnd) {w f.ReadLine(),!}
s f=""
d ##class(%File).Delete(tFileName)Anything with this flag can change or be removed with no warning.There are a few comments:
Let's say that the developers changed something in new versions of the DBMS. Is this a problem?
It is enough to check Caché Recent Upgrade Checklists, where usually there is a ready list of changes that may affect existing user code, for example.
Note that this can apply to absolutely any member of a class, and not even marked as [Internal]. Suffice it to recall the recent story with JSON support.
For a class does not exist flag [Internal], the warning is only on the level of comments.
As for the other members of the class, according to the documentation this flag is for other purposes, namely:Internal class members are not displayed in the class documentation. This keyword is useful if you want users to see a class but not see all its members. proof
This is what makes the method RunCommandViaZF
Does this example need to handle this?
Correct, of course, to close the device:
#include %systemInclude #dim cDev As %String = $IO ; see "dir /?" and RunCommandViaZF() d ##class(%Net.Remote.Utility).RunCommandViaCPIPE(...,.dev,.con) /* ... */ c:($get(dev)'="") dev:"I" u cDev
Also, do you not worry that its an internal class?
No, since for me internal ≠ deprecated.
However, given the openness of the source code, you can make own similar method, thereby to protect yourself from possible issues in the future.
<...> but maybe there's a better solution?
Yes, of course.
E.g. (for Windows x64):
#include %systemInclude
; see "dir /?"
d ##class(%Net.Remote.Utility).RunCommandViaCPIPE($$$FormatText("dir /A-D /B /S %1",$$$quote("C:\Program Files (x86)\Common Files\InterSystems")),,.con)
; string -> array
d ##class(%ListOfDataTypes).BuildValueArray($lfs($e(con,1,*-2),$$$NL),.array)
zw array