Find

Article
· Sep 4 2m read

Link tables programmatically

InterSystems FAQ rubric

In InterSystems IRIS, you can create linked tables using commands, instead of using System Explorer > SQL > Wizard > Linked Tables in the Management Portal:

To create a linked table, use the CreateLinkedTable method of the %SYSTEM.SQL.Schema class. See the class reference for details.

To execute it, follow these steps:

set sc = $SYSTEM.SQL.Schema.CreateLinkedTable("<dsn>","<Schema>","<Table>","<primaryKeys>","<localClass>","<localTable>","")

/// 1st argument: dsn - SQL Gateway connection name
/// 2nd argument: Schema - Source schema name
/// 3rd argument: Table - Source table name
/// 4th argument: primaryKeys - Primary key
/// 5th argument: localClass - Linked class name (e.g., User.LinkedClass)
/// 6th argument: localTable - Linked SQL table name (SqlTableName)
/// 7th argument: columnMap - Linked field information

If you run it this way, the linked table will be created with the ReadOnly attribute. If you want to remove the ReadOnly attribute, you need to specify it in the seventh argument, columnMap.

set columnMap("external field name") = $lb("new class property name","new sql field name","read-only(1/0)")

In this  sample, a columnMap is created that sets ReadOnly to 0 for all fields (columns), and a linked table is created. The primaryKey is set to inherit the primaryKey of the linked table. The usage is as follows:

do ##class(ISC.LinkUtils).LinkTable("<dsn>","<Schema>","<Table>","<localClass>")

/// First argument: dsn - SQL Gateway connection name
/// Second argument: Schema - Link source schema name
/// Third argument: Table - Link source table name
/// Fourth argument: localClass - Link destination class name (e.g., User.LinkedClass)

You can also see the sample used here: https://github.com/Intersystems-jp/CreateLinkedTable

Discussion (0)0
Log in or sign up to continue
Question
· Sep 4

About %Stream.TmpCharacter

Dear, Community!

I have a concern about using %Stream.TmpCharacter for storage purposes. Reading the class's source code, I can understand a bit about how it works. But I'd like to know from the community how it actually works. Is it necessary to use the .Clear() method to clear this buffer, or is it done automatically upon disposal?

Note: Please forgive my poor English.

6 new Comments
Discussion (6)3
Log in or sign up to continue
Digest
· Sep 4

Last chance to cast your vote in the InterSystems Demo Games!

Dear Community Member,

We’re entering the final stretch of the InterSystems Demo Games voting period! You’ve seen how our Sales Engineers bring InterSystems technologies to life through creative demos. At this time, all the demos are in. Now it’s time to make your voice heard!

👉 How to vote:

  1. Watch the demos on the Demo Games Contest Page.
  2. Select your favorite entries before September 14, 2025.

Your vote will decide the winners, so don’t miss the chance to support the demos that inspired you the most.

🔗 Full contest details here

Thank you for being part of the Demo Games — and may the best demo win! 🏆

Discussion (0)0
Log in or sign up to continue
Article
· Sep 4 4m read

Comment créer une méthode exploitable avec 50 paramètres ou utiliser le JSON comme qualificateurs de méthode

Salut tout le monde !

Parfois, lorsqu’on conçoit une méthode de classe et qu’on y ajoute de plus en plus de fonctionnalités utiles, le nombre de paramètres peut rapidement atteindre 10, voire plus.

Cela devient alors assez difficile pour les utilisateurs de ces méthodes utiles de se rappeler de la position des paramètres importants, et il devient très facile de se tromper en inversant des valeurs entre paramètres.

Voici un exemple d’une telle méthode (j’ai demandé à GPT de me créer une méthode avec 20 paramètres) :

ClassMethod GenerateReportWith20Params(
    pTitle As %String = "",
    pAuthor As %String = "",
    pDate As %String = "",            // ex. 2025-09-03
    pCompany As %String = "",
    pDepartment As %String = "",
    pVersion As %String = "1.0",
    pFormat As %String = "pdf",      // pdf|html|docx
    pIncludeCharts As %Boolean = 1,
    pIncludeSummary As %Boolean = 1,
    pIncludeAppendix As %Boolean = 0,
    pConfidentiality As %String = "Public",
    pLanguage As %String = "en",
    pReviewers As %String = "",      // CSV, ex. "Alice,Bob"
    pApprover As %String = "",
    pLogoPath As %String = "",
    pWatermarkText As %String = "",
    pColorScheme As %String = "default",
    pPageSize As %String = "A4",
    pOrientation As %String = "Portrait",
    pOutputPath As %String = "report.pdf"
) As %Status
{
    // implémentation
}

Magnifique, n’est-ce pas ? :)

Et voici un exemple d’utilisation, en ne fournissant que les paramètres 1, 2, 5, 13 et 19 :

Do ##class(Report.Generator).GenerateReport(
    "Rapport Financier Annuel",   // 1 : pTitle
    "Jane Doe",                   // 2 : pAuthor
    ,,                            // 3–4 sautés
    "Finance",                    // 5 : pDepartment
    ,,,,,,,                       // 6–12 sautés
    "Alice,Bob",                  // 13 : pReviewers
    ,,,,,                         // 14–18 sautés
    "Landscape"                   // 19 : pOrientation
    // 20 (pOutputPath) omis -> valeur par défaut utilisée
)

Une soupe de virgules.

Il existe bien sûr plusieurs manières d’atténuer ce problème. C’est là, par exemple, que l’approche JSON peut être très utile. J’ai découvert cette utilisation dans la très utile bibliothèque bdb-sql-utils de @Benjamin De Boe, par exemple ici, où les paramètres sont fournis sous forme de JSON puis analysés dans la méthode :

do ##class(bdb.sql.InferSchema).BuildAll("/tmp/data-dump/*.csv", { "verbose": 1, "targetSchema": "MySchema" })

J’ai trouvé ça très malin et j’ai utilisé la même approche dans la bibliothèque csvgen, où j’ai introduit la méthode Gen() (alias de Generate()), qui accepte 6 paramètres raisonnables au lieu de 11.

Signature de Generate :

/// génère une classe à partir d’un CSV arbitraire. Toutes les propriétés sont VARCHAR(250)
/// fncsv - chemin vers le fichier CSV
/// dlm - délimiteur
/// pguessTypes - tentative de deviner les types
/// pclass - nom de la classe (si non fourni, il sera généré et renvoyé par référence)
/// recordCount - nombre d’enregistrements créés (renvoyé par référence)
/// pverbose=1 - affiche des commentaires dans le terminal
/// pappend=0 - ajoute les données à une classe existante si activé
/// ploaddata=1 - utilise LOAD DATA si disponible
/// pheader=1 - saute la première ligne (entête)
/// pkey - si renseigné, définit une colonne comme clé primaire
ClassMethod Generate(fncsv As %String, dlm As %String = ",", ByRef pclass As %String, ByRef prowtype As %String, pguessTypes As %Boolean = 1, Output recordsCount As %Integer, pverbose As %Boolean = 1, pappend As %Boolean = 0, ploaddata As %Boolean = 1, pheader As %Boolean = 1, pkey As %String = "") As %Status

Signature de Gen :

///  do ##class(community.csvgen).Gen("/tmp/data-dump/file.csv",,"package.class",,{ "verbose": 1, "guessTypes": 1, "append": 0, "LoadData": 1, "header": 1, "primaryKey": "colname" },.recordsCount)
ClassMethod Gen(fncsv As %String, dlm As %String = ",", ByRef pclass As %String, ByRef prowtype As %String, qualifiers As %String = "", Output recordsCount As %Integer)

À l’intérieur de la méthode, le JSON est analysé dans une variable clé-valeur, ce qui permet de traiter les paramètres de manière plus souple :

ClassMethod FlattenQualifiers(ByRef qf, obj As %DynamicObject, prefix As %String = "") [ Internal, Private ]
{
    set iterator = obj.%GetIterator()
    while iterator.%GetNext(.key, .value) {
        set sub = $s(prefix="":$$$LOWER(key), 1:prefix_"."_$$$LOWER(key))
        if $isobject(value) {
            do ..FlattenQualifiers(.qf, value, sub)
        } else {
            set qf(sub) = value
        }
    }
}

Et voici un exemple d’appel, lorsque l’on veut définir une clé primaire :

Appel de Generate :

set status=##class(community.csvgen).Generate(fn,",",.pclass,.prowtype,1,.tResults,,,,,"name")

Je dois taper 5 virgules avant de pouvoir fournir le paramètre voulu.

Appel de Gen :

set status=##class(community.csvgen).Gen(fn,",",.pclass,.prowtype,{"verbose":1,"primarykey":"name"},.tResults)

Ici, je fournis uniquement les paramètres dont j’ai besoin, et il est clair de voir ce qui est spécifié. C’est pourquoi je voulais partager cette expérience avec vous, formidable communauté de développeurs InterSystems !

Encore merci à @Benjamin De Boe et à JSON, qui rendent la vie plus simple pour les développeurs ObjectScript !

Bon codage à tous !

Discussion (0)1
Log in or sign up to continue