Error when attempting to instantiate an ABC compliant CLASS - Baffled & beaten!

,

Do you have a “data” dll or is this a single APP solution?
If you have a data dll that exports all the classes and tables from your dictionary, the ABC compliant classes are automatically included.

If I know what you’re talking about :), that is a template to generate a instance of the class into a procedure and include Embed points for each method’s data and code sections. Similar to what an ABC Browse class looks like in a procedure.

I thought that was only with the global DLL, or the EXE without EXTERNAL.

Thanks for all the input, @MarkGoldberg, @Rick_UpperPark and @jslarve … I’m back again (I’m in a different time-zone here; Australia being many hours ahead of the US of A)

Yes, that’s it - - and because it “simply works” I assumed it was part of the magic of an ABC compliant class … but, actually, it’s template-implemented.

To confirm this, I dug into the example of Mike Hanson’s TabPopup template (from a very early version of the SuperStuff template set) … and I found this;
image

… which adds an INCLUDE statement for each PROCEDURE containing a Sheet control

image - Revealed only via Module mode !

ABC compliance is playing a part - - as that must be how the reference to ‘MH::TapPopup’ is able to be translated to a reference to the MHABTABP.INC container for the Class declaration

John M

Yep, all sorted, Mark … and now ready to “circle back”.

Regards, John M

Hi John

just an aside, I think that these days as you can use “ONCE” on your include:

INCLUDE('jmExtName.inc'),ONCE

it is no longer necessary to have the boiler plate omit:

OMIT('_EndOfInclude_',_jmExtName_) ! Omit if already compiled
_jmExtName_ EQUATE(1)

although I guess it doesn’t do much harm… just unnecessary

cheers for now

Geoff R

Thanks, Geoff - I wasn’t aware of that refinement.

Note: There was a small bug in the .INC/CLW files I posted at top of this thread (with big implications; I had the wrong INC file referenced from within the CLW !!). New copies posted here;

jmExtNAME.CLW (1.2 KB) jmExtNAME.INC (1.1 KB)

… with an accompanying template for implementation … jmExtName.TPW (1.7 KB)

John

Some new enhancements;

Filename (1st parameter) can now be OMITTED after first usage … Retained via a STATIC variable.
jmExtNAME.CLW (1.6 KB) jmExtNAME.INC (732 Bytes)

Usage examples included as comments, via the implementation template.
jmExtName.TPW (2.8 KB)

Observations and/or suggestions welcomed …

John

I Agree about using ,ONCE instead of relying the OMIT and EQUATE(1)
especially if you’re using the SV.IDE, IIRC using ONCE results in faster code completion

For other feed back.

  • IMO Ideally the name of the file for the .inc/.clw should match your class name
    that said, ‘:’ isn’t valid in a filename

  • The class name and methods talk about ExternalName
    but the method is returning the result of WHO()

    Do you want to change the result of the method to use
    pFile{PROP:Name, N} where N= WHERE( TheGroup, pField )
    or do you want to rename the class and methods ?

  • Have you considered gettting rid of ExternalName property?
    While it is set, it’s never read, and it’s private
    While it is use as a return value,
    you could instead use a variable inside of each of the methods

  • in your first method .ExtName(FILE pFile)
    the call to SELF.ExtName(pFile, SELF.ExternalName) looks wrong to me
    the 2nd parameter should be a field in a file buffer, not SELF.ExternalName
    note: I haven’t compiled, much less tested any of this

  • the use of ,STATIC on the method variable RecordStructureRef
    allows you to omit the pFile on additional calls
    yes, that will work – but it’s not thread safe
    if you really want to make calls like

    oGetExtName.ExtName( myFile, myFile.ID )
    oGetExtName.ExtName(            , myFile.Description)
    

    then I would move the &GROUP (and/or &FILE) to class properties
    in truth, i’d probably split some logic out.
    yada.Current( MyFile ) ! set SELF.TheGroup &= pFile{PROP:Record}
    and / or
    yada.Current( MyFile.Record ) ! set the SELF.Group &= pGroup

    TheName = yada.GetExtName( MyFile.ID )

Many thanks for your detailed critique, Mark … I appreciate the time/effort you’ve made :+1:

As for any new class, I guess, this has been an iterative process - the latest (renamed) version follows;
jmSQLName.CLW (2.4 KB) jmSQLName.INC (867 Bytes) jmSQLName.TPW (3.3 KB)

Some background;

I’ve always addressed SQL tables via Clarion’s View paradigm - with the “key” to successfully doing so being specification of the SQL server-side labelling of table & column names via the Clarion dct’s External Name attribute = Prop:Name.

All the same, I’ve come across some occasional cases where it’s been necessary to cast some “raw” SQL code (such as for GROUP BY & HAVING statements, specified via the SQL Advanced tab) - - BUT, doing so with server-side syntax within STRING variables means that it’s hidden from the Clarion compiler … and I’d rather have the compiler validate ALL my code, rather than deal with strange bugs after the fact.

So, this class enables me to build compiler-validated SQL statements, using Clarion syntax.

For example, this:


Results in this;

SELECT AppUsage.AppUsageRID,AppUsage.AppUserRID,AppUsage.Date,AppUsage.Time FROM AppUsage WHERE AppUsage.AppUsageRID = 99 ORDER BY AppUsage.AppUserRID


Done - Thanks to Geoff @vitesse for this one; I was naively copying other class definitions.

I use Mike Hanson & Vince Sorensen’s classes & templates as guide/inspiration for my own dabbling; I’m copying their conventions in this case. All the same, I concur with your point on consistency - and I’ve renamed the methods and INC/CLWs accordingly.

WHO returns the field name … that’s what I intend the class to do. The WHERE provides a reference to the specific field. Since I need the WHERE, it just seemed consistent to me to use WHO (instead of PROP:Name) … I “borrowed” the concept from ViewManager.GetFieldName - - ABFILE.CLW

Point taken. Fixed.

Yes, I admit that is a bit of a fudge ! … but I needed (any old) variable to pass as the 2nd parameter - and SELF.ExternalName was handy :wink:

Oops ! - Whilst I had not considered the complications/implications of thread safety, I originally tried declaring the &GROUP reference variable as a class property - but the complier did not like the STATIC attribute in there, which is why I moved it to the method.

Mmm - pondering (I’m writing this in real-time !);

  • Why would thread safety be an issue here ? - - The Class is derived/declared within a Procedure - so, presumably(?), the scope of all its variables is limited to the specific Procedure - and separate from any other Procedures that may have their own instance. What am I not appreciating ?

  • Ahhh !! … The penny drops (with regard to the STATIC issue); I don’t need the STATIC attribute if the &GROUP reference variable is declared at the class level - 'cos it’s then in-scope for all locally instantiated class methods. Oh, der !

  • I’m still not clear/sure about the thread safety issue - Is it OK now (and why was it not before) ? - and, do I need a THREAD attribute on the class (and if so, why) ??


Thanks once again for your help with this, Mark - it’s now a much better design, as a result.

I’ve included all fixes/enhancements in the files attached above.

Regards, John M

1 Like

While Bruce might suggest otherwise, I am firmly of the belief to avoid the SQL Advanced tab, simply create this type of view on the backend, and define the view in the Dct as a table. In addition to having the compiler validate the code, this approach is not Clarion-centric, allows one to later optimize sub-queries on the backend without changing your program, and can permit multi-table updates using an trigger on the view.

GetSQLName.clw (2.6 KB) GetSQLName.inc (1.1 KB)

Please look carefully at the attached files.
Bug found: replace xWho with pWho in the .StripPrefix method

I agree, Douglas - and that’s exactly how I’ve handled this situation myself. I had someone else in mind, tho, when I wrote this class/template, who has limited SQL server-side skills.

John

That’s a much more elegant solution, Mark … :+1:

May I push my luck with some clarification questions (?)

  • BOOL is (via EQUATES.CLW) a SHORT data type … Why is that preferable to a BYTE for T/F ?

  • You present 2 methods to return a given field’s “name”; one based on WHO and the other based on Prop:Name. As I understand it, they yield exactly the same result (right?)
    – Why/when would you use one in preference to the other ?

  • I don’t understand the purpose of the .CleanName method; what are the “Extended Name notations as created by Capesoft” ?

Thanks again …

John M

Yeah, the bit twiddling performance oriented part of me doesn’t like the extra byte, and since numeric expressions track back to LONG we don’t really have a win there either.

That said, I like the clarity that BOOL brings to the table.
To me, BOOL says TRUE|FALSE, whereas BYTE says number.

WHO and PROP:Name might return the same thing,
but it’s not the case that they always will return the same thing.

You can declare an external name for a field (or variable)
SomeField STRING(42),NAME(‘DifferentName’)

It’s my understanding that the Clarion SQL file drivers will use the NAME attribute for column names. Which is precisely what you are working on. So I think you should use PROP:Name instead of WHO.

A Proposed Convention for the Extended use of the Name Attribute - code - ClarionHub

If I’m not mistaken Capesoft uses the Extended Name attribute for reflection work to drive xFiles and JFiles behavior. But the idea isn’t limited to just those two cases, it could be used for all sorts of things.

The purpose of the .CleanName method is to provide the class equivalent of an embed point, by calling a ,VIRTUAL method - which can then be derived.

2 Likes

It’s actually SIGNED, which is LONG in Clarion 32 bit.

1 Like

Even worse. :slightly_smiling_face:

I wish we could be complaining that it’s INT64.

Perhaps not worse when passed. Base type for anything less than a LONG is still a LONG.

1 Like

Haha - Yes, I was hoping no-one would notice my mistake :wink:

Aahh - That’s a good point. On that basis, I’m now happy with BOOL.

John