Comparaison des versions

Légende

  • Ces lignes ont été ajoutées. Ce mot a été ajouté.
  • Ces lignes ont été supprimées. Ce mot a été supprimé.
  • La mise en forme a été modifiée.

Le service web RecordSql est une fonctionnalité native du runtime, disponible en mode REST uniquement.

Info

Paramétrage

Le paramétrage du SW RecordSql doit être effectué en amont pour lister les RecordSql autorisés

La demande d'action RecordSql au service web REST se fait au format JSON dans le corps du message.

Il permet a un appelant, après avoir passé les informations d'authentification, d'interroger un RecordSql directement afin d'obtenir des données de la base de données, sans entrer dans la gestion de l'ERP et donc sans invoquer de programme Diva car cette API s'en charge directement.

Info

Rappel

Les RecordSql sont des objets compilé en Diva (extension .DHOQ) qui contiennent un ensemble de requêtes SQL.

Ces requêtes SQL comportent la table, les champs, les jointures, les clauses WHERE, etc...

L'appelant et le paramétrage du service web détermine dans quel contexte (environnement, utilisateur, implicite)  les données vont être lues.

Format de la demande

Paramètre

Balise

Description

Nom dictionnaire RecordSql

"dhoq"

(obligatoire)

Nom du dictionnaire record sql : c’est le fichier .dhoq.

Par exemple GTRSART.dhoq contient plusieurs RecordSql liés aux articles

Nom RecordSql

"recordsql"

(obligatoire)

Nom du record sql unitaire : correspond a la balise <RecordSql du dictionnaire.

Par exemple Article est la requête SQL principal de la base articles

Token

"access_token"

(obligatoire)

Valeur du TOKEN obtenu durant la phase d'authentification

Paramètres 

"parameters"

Liste des champs et leurs valeurs (en majuscules et en précisant le nom de table) au format table.champ=valeur séparés par le point-virgule.

Ce champs servent de référence en tant que clé pour exécuter la requête. Par défaut ce champ reste vide car le moteur REST cherche s’il peut remplir tout seul les paramètres variables pour traiter la requête, en se basant sur la table des utilisateurs  et les tables communes de l’ERP.

En principe ce champ devrait être toujours vide, à part quelques exceptions, sinon il doit contenir une suite de champs .

Exemple : MZ.DOS=998 ; etc

Champs à récupérer

"fields"

Liste des champs à récupérer, en majuscules et sans préciser la table, séparés par un point virgule.

Par défaut * indique qu’on veut récupérer tous les champs de la table.

Exemple  CPOSTAL;VIL

Note : pour les champs provenant d'une jointure soit on utilise l'alias (si existant dans le recordSql), soit on utilise le nom de la table jointée avec le nom du champ séparés par un '_'. Exemple : jointure sur ART, la récupération du champ ART.REF s'obtient avec l''écriture du champ ART_REF

Attention, ce sont les champs renvoyés par le service web, et pas ceux retournés par la requêre SQL. Pour optimiser la requête, il convient d'utiliser les options

Condition where

"where”

Nom de la condition where existante dans le RecordSql

Le programme XRecordSQLCheck.exe vous permet de connaitre le contenu des fichier .dhog avec la liste des recordSQL qu’ il contient et pour chacun la liste des clauses where, des tris et des clauses having ainsi que les paramètres à transmettre.

Paramètres where

"where_parameters"

Liste des paramètres de la condition where selon le RecordSql au format nomDuParametre1=valeur1;nomDuParametre2=valeur2 ou directement les valeurs au format valeur1;valeur2 dans ce cas les conditions sont appliquées dans l’ordre d’apparition

Pour les champs valeur de type ‘chaîne de caractères’, ne pas mettre de cote ou double cote pour les chaines

Pagination offset

"offset"

Mettre une valeur > 0 pour récupérer un nombre important d'enregistrements. Voir plus loin au sujet des lectures en mode pagination pour renvoyer les enregistrements en plusieurs fois, sachant que le serveur est configuré pour une valeur maximale du nombre d'enregistrements

La valeur 0 équivaut a la valeur 1, c'est à dire que seul le premier enregistrement sera retourné.

Pagination count

"count"

Tri

"orderby"

Nom du tri orderby du RecordSql : nom tel qu'il apparaît par exemple Par_Ref

Condition having

"having"

Nom de la condition having

Paramètres having

"having_parameters"

Paramètres de la condition having

Filtres SQL

"filter"

Filtres avancés concernant les clauses WHERE et la gestion des jointures (voir plus bas)

Informations

"infos"

Informations complémentaires, notamment sur la performances ou versions (voir plus bas)

Info

Header

Un HEADER est uniquement utilisé pour indiqué le Content-Type : application/json  , mais pas de header d'authentification puisqu'elle passe par le champ "access_token" du corps

Astuce

Espacements

Les 'espaces' sont interdits dans les noms de balises.

Exemple :  un appel "dhoq " (donc un espace en trop) provoque une erreur 

L'URL a utilisé pour les demandes d'action RecordSql est sous la forme : base commune de l'URL + '/api/v1/RecordSql/Execute'

Exemple d'URL sur un poste local:

http://localhost:8080/DhsDivaltoServiceDivaApiRest/api/v1/RecordSql/Execute

Exemple d'URL en Divalto cloud:

URL : http://api.divaltocloud.com/123456/testing1/api/v1/RecordSql/Execute

Informations complémentaires : gestion des dossiers et utilisateur

L'authentification permet d'identifier, via les utilisateurs Harmony, un utilisateur Divalto. Cet utilisateur doit bénéficier dans le paramétrage Divalto d'un dossier par défaut

C'est ce dossier qui est appliqué par défaut lors d'une appel API RecordSql.

Pour modifier le dossier, il faut indiquer le nom du dossier dans la zone 'parameters' sous la forme suivant

"parameters" :  "MZ.DOS=MONDOSSIER"

Informations complémentaires : gestion des jointures

Le champ 'filter' peut contenir les commandes suivantes:

<joinactivate>

Nom de la jointure 

ou

$ALL

<joindeactivate>

<columnactivate>

Nom de la colonne

ou

$ALL

<columndeactivate>

Utilisation de ces options: 

  • Le fonctionnement de ces options est strictement le même que pour l'écriture en langage Diva (voir l'aide en ligne pour plus de détails)

  • Permet donc d'activer ou desactiver des jointures ou des colonnes, afin d'optimiser la lecture, ou de lire des champs de jointures optionnelles

  • L'utilité de ces options dépend de la manière dont le RecordSql a été écrit. Un RecordSql qui n'a pas de jointure activée par défaut sera optimisé sans cette option

  • Les noms de jointure ou $all sont toujours convertis en majuscules avant leur utilisation.

  • On peut combiner les options. Elle seront exécutées dans l'ordre d'apparition

Exemples 'infos':

filter= "<joindeactivate>$all"  ;permet de lire uniquement la table du FROM sans aucune jointure, donc de manière beaucoup rapide  

filter= "<joindeactivate>$all<joinactivate>majointure"   ;permet de désactiver toutes les jointures, puis de ne réactiver que la jointure 'majointure' 

Informations complémentaires : filtres SQL

Le champ "filter" permet l'utilisation de filtres SQL avancés pour la gestion des clauses WHERE 

Balise

Utilisation

"operator_where"

La valeur ‘OR’ permet d’appliquer un OU logique (Défaut : ET)

"where"

Définition des clauses WHERE

"whereaddcondition”

Définition des conditions entre les clauses WHERE.

name : nom de la condition, par exemple “maCondition1”

condition : valeur de la condition, par exemple “where1 et (where2 ou where3)”

"createwhere"

Création de nouvelles conditions WHERE

"whereremovecondition"

Suppression de conditions WHERE spécifiques

"joindeactivate"

Désactivation des jointures vers les tables en dépendance

Les mécanismes appliqués sont ceux des RecordSql Diva.

Remarque

L’utilisation de la balise “filter” pour décrire les conditions est incompatible avec les balises “where” et “whereparamaters” du niveau supérieur (réservé pour le cas simple d’une seule condition where)

Conditions where simple

Pour positionner une condition where simple il n’est pas utile de passer par la balise “filter”

Bloc de code
languagejson
"where":"Equal_Vil",
"where_parameters":"ENTZHEIM",
// Utilisation des basises WHERE et WHERE_PARAMETERS pour un cas de clause unique

Conditions where multiple en combinaison simple ET

Pour positionner de multiples conditions where avec un ET logique, il s’agit d’indiquer les noms des clauses WHERE et leurs paramètres, mais le record SQL faisant par défaut un ET logique, il n’est pas utile de donner plus d’information

Bloc de code
languagejson
"filter": {  
        "where": [
            {"name":"LIKE_VIL", "parameters":"EN%" },           
            {"name":"LIKE_CPOSTAL", "parameters":"67%" }        
            ] 
          }
// Première clause WHERE 'Equal_vil' et la valeur demandée 'ALBI'
// Seconde  clause WHERE 'Like_CPostal' et la valeur demandée '67%' pour obtenir les 67****
// Par défaut, un ET logique est appliqué

Conditions where multiple en combinaison simple OU

Pour positionner de multiples conditions where avec un OU logique, il s’agit d’indiquer les noms des clauses WHERE et leurs paramètres, et d’indiquer le type d’opérateur OU

Bloc de code
languagejson
"filter": {  
        "where": [
            {"name":"EQUAL_VIL", "parameters":"ALBI" }, 
            {"name":"EQUAL_VIL", "parameters":"TOULOUSE" }
            ], 
        "operator_where":"OR"
          } 
// Première clause WHERE 'Equal_vil' et la valeur demandée 'ALBI'
// Seconde  clause WHERE 'Equal_vil' et la valeur demandée 'TOULOUSE'
// Deux clauses WHERE avec un OU logique

Conditions where multiple en combinaison complexe

Pour positionner de multiples conditions where en combinaisons complexe avec parenthésage, ET logique, OU logique, il s’agit d’indiquer les noms des clauses WHERE et leurs paramètres, et d’indiquer la condition complète

Bloc de code
languagejson
"filter": {  
        "where": [   
            {"name":"EQUAL_VIL", "parameters":"ENTZHEIM" },               
            {"name":"LIKE_VIL", "parameters":"%OBER%" },                  
            {"name":"LIKE_CPOSTAL", "parameters":"67%" }                  
            ], 
        "whereaddcondition":                                              
            { "name":"cond1", "condition":"(Like_Cpostal and Equal_Vil) or Like_Vil" }            
          } 
          
// Première  clause WHERE 'Equal_vil' et la valeur demandée 'ENTZHEIM'
// Seconde   clause WHERE 'Like_vil' et la valeur demandée '%OBER%' pour obtenir les *OBER*
// Troisième clause WHERE 'Like_CPostal' et la valeur demandée '67%' pour obtenir les 67****
// Définition de la condition complexe : (Like_Cpostal and Equal_Vil) or Like_Vil

Conditions where spécifique en combinaison complexe

Pour positionner de multiples conditions where spécifiques (non prévue dans le recordSql) en combinaisons complexe avec parenthésage, ET logique, OU logique, il s’agit d’indiquer les noms des clauses WHERE et leurs paramètres, et d’indiquer la condition complète

Bloc de code
languagejson
"filter": {  
       "whereremovecondition" :                                               // Toujours demander a effacer les conditions que l'on veut créer
        { "name":"", "parameters": "CONDVILLE1;CONDVILLE2;CONDVILLE3" }, 
       "createwhere":                                                         // Création temporaire de conditions spécifiques (inexistant dans le recordSql)
         [ 
            { "name":"CONDVILLE1", "condition": "T057.VIL='STRASBOURG'" },    // Première  clause WHERE avec le nom attribué, et sa valeur construite directement à partir du nom de champ
            { "name":"CONDVILLE2", "condition": "T057.VIL='TOULOUSE'" },      // Seconde   clause WHERE avec le nom attribué, et sa valeur construite directement à partir du nom de champ
            { "name":"CONDVILLE3", "condition" : "T057.VIL='ALBI'"}           // Troisième clause WHERE avec le nom attribué, et sa valeur construite directement à partir du nom de champ
         ], 
       "whereaddcondition":                                                   // Définition de la condition complexe en utilisant les conditions créés
            { "name" : "CONDTEST", "condition": "CONDVILLE2 OR CONDVILLE3" }  // CONDVILLE1 n'est pas utilisé, d'où sa suppression préalable
          } 

Informations complémentaires : performances et compteurs

Le champ 'infos' peut contenir les commandes suivantes:

<perf>

1

Performances et compteurs

<version>

1

Version du module REST

<perfmem>

1

Mesures mémoire

<debugctx>

1

Debug du changement de contexte dossier

<infostoken<

1

Informations sur la durée et expiration du token

Balise perf

La balise xperf à 1 indique que le demandeur souhaite obtenir des informations générales et de performances sur l'exécution de la demande.

Si la balise est donnée lors de l’authentification, toutes les demandes utilisant le token correspondant se feront avec réponse de performances.

Sinon le demandeur peut demander les performances demande par demande.

La réponse est obtenue dans la balise "infos" de la réponse. Voir plus bas pour le format de la réponse.

Exemple de demande : "infos" : "<perf>1"

Balise en réponse à un demande de performance

Contenu et détails

ExecuteSQLAuth

Durée totale de la demande d’authentification

ExecuteRequestSQL

Durée totale d’une requête

LoadCommunTables

Durée totale de la lecture des tables communes a tous les utilisateurs

LoadUserTables

Durée totale de la lecture des tables pour cet utilisateur

LoadUser

Durée totale de tout ce qui esprecedent

LoadAuthTables

Durée totale de la lecture des autorisations pour cet utilisateur

LoadDatasDiciotionary

Durée totale de la lecture du dico

CountDictionary

Nombre de dico

CountDictionaryLoadByDHXISAM

Nombre de dico ouvert par dhxisam

CountDictionaryLoadByXML

Nombre de dico ouvert par xml 

CountDictionaryLoadByJSON

Nombre de dico ouvert décodage json

LoadDHOQ

Durée de chargement du dhoq et des ses surcharges

LoadDHXISAM

Durée de chargement de dhxisam avec xlogf

LoadDataForSQL

Lecture des datas du recordsql provenant du dico

LoadRecordForSQL

Lecture du recordsql

ExecuteSQL

Durée totale de executesql

ResultSQL

Durée de mise en format du resultat de la requête

ImpersonationSQL

Durée de demande d’impersonationa sqlserveur

Balise version

La balise version à 1 indique que le demandeur souhaite obtenir la version du module REST.

La réponse comporte la balise VersionRest indiquant cette version, et le cas échéant la balise DebugRest à 1 si le mode debug est activé

Exemple de demande : "infos" : "<version>1"

Exemple de réponse

Bloc de code
"infos": "{
"VersionRest":"3.05",
"DebugRest":"1"
}"

Balise perfmem

La balise perfmem à 1 indique que le demandeur souhaite, en plus des performances de base, obtenir aussi des détails sur la consommation mémoire en cours du processus REST

La réponse comporte plusieurs balises, celles de <perf> et aussi de nouvelles balises sur la mémoire

Exemple de demande : "infos" : "<perfmem>1"

Balise en réponse à un demande de mémoire

Contenu et détails

TimeExecuteAuthentification

temps total de la requête d'authentification

CountNumberExecuteRequeteSQL

nombre de requête sql (authentification fait plusieurs requêtes pour lire les infos du compte dans l'erp

CountDHOQ

nombre de fichiers dhoq chargé,ils contiennent les recordsql

TimeLoadDHOQ

temps qu'on mis pour charger ces fichiers dhoq en mémoire ce temps dépend surtout de xlan (si ces infos ne sont pas présentes, c'est que le chargement des dictionnaires est déjà en mémoire

CountNumberDictionary

nombre de dictionnaires diva chargés total

CountNumberDictionaryLoadByXM

dont ceux qui sont chargés sous forme de xml (donc chargement optimisé)

CountNumberDictionaryLoadByDHXISAM

dont ceux qui sont chargés par xlan (donc chargement non optimisé)

CountNumberDictionaryLoadByJSON

ancien systeme de structure des dicos

TimeReadDatasDictionary

et le temps global que cela a mis pour lire tous les dictionnaires

CountLoadDHXISAM

nombre d'appel a xisam pour lire les implicites de l'utilisateur et xlogf

TimeLoadDHXISAM

et temps que cela a pris

TimeSQL

temps qu'on mis pour faire la gestion des requêtes (donc hors lecture des dicos et des dhoq et de xlogf)

CountSQL

nombre de requêtes totales (quand on fait une authentification cette valeur est la mêmeque CountNumberExecuteRequeteSQL)

Quand on execute une requête , il y a plusieurs étapes :

TimeReadLocales

etape 1 temps de traitement des champs pour la requête

TimeReadDatas

etape 2 temps de traitement des champs provenant des dicos

TimeReadDatas_CreateList

création de listes

TimeImpersonation

etape 3 temps qu’ on a mis pour passer en mode impersonation pour exécuter les requêtes

TimeExecuteRequestSQL

etape 4 execution de la requête

TimeReadResult

etape 5 temps pour lire le retour des résultats de la requête (lecture des champs mais aussi traitement des confidentialitées)

TimeReadResult_ControlConf

et on a le détail sur le traitement des confidentialités

TimeReadResult_SetDatasInResul

et on a le détail sur la copie des champs vers la table du résultat que renverra la requête REST

CountNumberRecord

ce qui a donné un nombre de record a lire

CountNumberDatasRecord

et la liste des champs à traitées pour faire une authentification on a besoin de lire les tables de droits d'accès de l'erp et les paramètres du compte ( dossier , dépôt , options de l'utilisateurs etc)

CountNumberRecordAuth

nombre de records pour traiter l'authentification erp

CountNumberDatasRecordAuth

nombre de champs

CountNumberRecordCommun

nombre de records des tables communes

CountNumberDatasRecordCommun

nombres de champs

CountNumberRecordType

nombre de record des types pour effectuer les recherches dans le dossier

CountNumberDatasRecordType

nombres de champ

TimeLoadAuthTablesForUser

TimeLoadUserTableForUser

TimeLoadCommunTablesForUser

ce qui donne un total

TimeGlobalLoadInfosUser

apres c'est juste informatif , c'est le temps qu'on a passé pour les records sql de l'erp pour charger la config d'un utilisateur

TimeGtrstabTablecommune

TimeWmrstabTcommun

TimeA5rsdosUtilisateur

TimeGtrsdosDossiercrm

TimeA5rsdosAppliautoris

TimeGtrsdosDossier

NonpagedSystemMemorySize

PagedMemorySize

PagedSystemMemorySize

WorkingSetMemorySize

PeakPagedMemorySize

PeakVirtualMemorySize

PeakWorkingSetMemorySize

VirtualMemorySize

Interprétation des informations mémoire :

  • La taille de la mémoire virtuelle « PeakVirtualMemorySize » : taille de mémoire adressable par un processus, rien ne peut dépasser ces valeurs.

  • Il faut donc surveiller WorkingSetMemorySize et PeakWorkingSetMemorySize, et aussi PagedMemorySize, PeakPagedMemorySize.

  • Car cela indique la charge de mémoire en cours (et le pic attient) et voir si on se rapproche plus ou moins vite de VirtualMemorySize.

  • Il faut donc faire plusieurs requêtes et suivre l'évolution de la mémoire, en sachant que la première requête va allouér la mémoire pour stocker les informations de la requêtes, et donc il faut surveiller la mémoire à partir de la deuxième requête.

Exemple de réponse a une demande de lecture de 10 codes postaux

Bloc de code
languagejson
infos: "{"xperf" : {	
"CountNumberExecuteRequeteSQL" : "1"	il y a 1 appel a l'api execute record sql
,"TimeExecuteRequestSQL" : "187"	il a mis 187 mili
,"TimeReadDatas" : "1"	on a mis 1 mili pour traiter les datas enntrées
,"TimeImpersonation" : "1"	impersonation
,"TimeReadResult" : "10"	lecture du résultat et des champs et traitement des confidentialités
,"CountLoadDHXISAM" : "1"	un appel pour voir si dhxisam est déjà chargée
,"TimeLoadDHXISAM" : "1"	le temps du test
,"CountSQL" : "1"	une requête effectuée
,"TimeSQL" : "1"	temps pour la requête
,"TimeGlobalLoadInfosUser" : "15"	test pour vérifier si les infos de l'utilisateur sont présentes
,"TimeReadLocales" : "1"	idem
,"CountNumberRecordAuth" : "13"	idem pour les autorisations
,"CountNumberRecordCommun" : "4"	idem pour les flags communs erp et les flag type de l'erp
,"CountNumberRecordType" : "1"	
,"TimeGtrstabCodepostal" : "172"	
,"NonpagedSystemMemorySize" : "79"
,"PagedMemorySize" : "158108"
,"PagedSystemMemorySize" : "606"
,"WorkingSetMemorySize" : "62484"
,"PeakPagedMemorySize" : "187976"
,"PeakVirtualMemorySize" : "1067052"
,"PeakWorkingSetMemorySize" : "212992"
,"VirtualMemorySize" : "822476
}}"
}

Balise debugctx

La balise debugctx à 1 indique que le demandeur souhaite obtenir, uniquement lors d’une DEMANDE AVEC CHANGEMENT DE DOSSIER, des détails sur le changement de contexte (=dossier courant).

La réponse comporte plusieurs balises.

Exemple de demande : "infos" : "<debugctx>1" précédé par "parameters" : "DOS=997"

Bloc de code
languagejson
{"debugctx" : {"debugctx_action":"dos= dos voulu=997 recordsql=TABLECOMMUNE,dos= dos voulu=997 recordsql=TCOMMUN,
dos= dos voulu=997 recordsql=UTILISATEUR,dos=997 dos voulu=997 recordsql=DOSSIERCRM,dos=997 dos voulu=997 recordsql=APPLIAUTORIS,
dos=997 dos voulu=997 recordsql=DOSSIER,dos=997 dos voulu=997 recordsql=PDOSSIER,dos=997 dos voulu=997 recordsql=DOSEXP,
dos=997 dos voulu=997 recordsql=EXPERT_GRM,dos=997 dos voulu=997 recordsql=EXPERT_QUAL,dos=997 dos voulu=997 recordsql=EXPERT_CONT,
dos=997 dos voulu=997 recordsql=EXPERT_DDOC,Création contexte sur dossier 997," }}

Lors d’un second appel, si le contexte mis en cache n’est pas modifié, la réponse l'indique

Bloc de code
{"debugctx" : {"debugctx_action":"Contexte déjà existant sur dossier 997" }}

Balise infostoken

La balise infostoken à 1 permet d’avoir des informations sur le token , notamment sur sa durée et la date/heure d’expiration.

La réponse comporte plusieurs balises.

Bloc de code
languagejson
"infos": "{
"InfosToken{":
"ExpireLocalTime":"20221228085340",	
"ExpireUtcTime":"20221228075340",	
"ExpireMinutes":"30",	
"ExpireLocalTimeName":"Paris, Madrid",	
"Env":"ERP213",	
"User":"jpt3",	
"Domain":"psxbdjpt01"	
}}"

Informations complémentaires : debug et fonctions spéciales

Demande <debug>1 et <sizedebug>10000

Demande Debug

Remarque

Attention cette commande ralenti l’exécution du module REST et elle est globale a tout le module REST

La balise <debug>1 positionnée dans la zone infos permet de mettre le module REST en mode debug.

Cela a pour effet d'écrire des lignes de debug dans le fichier \divaltolog\feventREST.log

En complément:

  • <sizedebug>xxxxxx Permet d’indiquer une limite de taille du debug

  • <debugloaddico>1 Permet de limiter le le fichier debug au chargement des dictionnaires

  • <dicojson>0 Permet d’indiquer de ne plus charger les dictionnaires pour optimisation (qui sont décrits dans les fichiers XML)

Demande DebugEnv

Cette fonction n’est disponible qu'à partir de la version Harmony 409a

La balise <debugenv>1 peut être positionnée dans la zone infos lors du PREMIER appel de la demande de jeton. En effet elle ne fonctionne que pour une nouvelle connexion avec un nouveau compte, lors du chargement des informations de l’environnement. Par la suite un cache stocke ces informations et l’appel avec cette balise n’a plus aucun effet

Exemple d’appel

Bloc de code
languagejson
{
    "domain":"{{DOMAIN}}",
    "user": "{{LOGIN}}",
    "password": "{{PASSWORD}}",
    "env": "{{ENV}}",
    "infos": "<debugenv>1"
}

La réponse donne des détails sur tout le cheminement du chargement d’un environnement (implicites, dhoq, fichiers,…)

Exemple de réponse

Bloc de code
languagejson
"infos": "{
"debugenv" : {
"cheminxlogfenv":"//PSXBDJPT01/Divalto/ERP213/fichiers",
"cheminxlogf":"//psxbdjpt01/divalto/erp213/fichiers",
"CheminDivalto":"c:\Divalto",
"CheminEtFichierImplicites":"//psxbdjpt01/divalto/erp213/fichiers/implicitesdemo.txt",
"CheminEtFichierImplicitesOpen":"//psxbdjpt01/divalto/erp213/fichiers/implicitesdemo.txt",
"CheminEtFichierImplicitesAuformatWindows":"c:\divalto\erp213\fichiers\implicitesdemo.txt",
"LectureFichier":"GTRSTAB.DHOQ",
"LectureFichier":"GTRSTAB.DHOQ",
"objetdhoq":"GTRSTAB.DHOQ",
"addon ErreurLectureFichier": \divalto\erp213\setup\specifs\objets\GTRSTABU.DHOQ (erreur 20),
"addon ErreurLectureFichier": \divalto\erp213\setup\specifs2\objets\GTRSTABU.DHOQ (erreur 20),
"LectureFichier":"//psxbdjpt01/divalto/erp213/fichiers/implicitesdemo.xml",
"ImplicitesLocales":"//psxbdjpt01/divalto/erp213/fichiers/implicitesdemo.txt",
"LectureFichier":"c:\divalto\erp213\fichiers\connexions.xml",
"ConnexionsLocales":"c:\divalto\erp213\fichiers\connexions.xml",
"cheminxlogfenv":"//PSXBDJPT01/Divalto/ERP213/fichiers",
"cheminxlogf":"//psxbdjpt01/divalto/erp213/fichiers",
"CheminDivalto":"c:\Divalto",
"CheminEtFichierImplicites":"//psxbdjpt01/divalto/erp213/fichiers/implicitesdemo.txt",
"CheminEtFichierImplicitesOpen":"//psxbdjpt01/divalto/erp213/fichiers/implicitesdemo.txt",
"CheminEtFichierImplicitesAuformatWindows":"c:\divalto\erp213\fichiers\implicitesdemo.txt",
"LectureFichier":"WMRSTAB.DHOQ",
"LectureFichier":"WMRSTAB.DHOQ",
"objetdhoq":"WMRSTAB.DHOQ",
"addon ErreurLectureFichier": \divalto\erp213\setup\specifs\objets\WMRSTABU.DHOQ (erreur 20),
"addon ErreurLectureFichier": \divalto\\erp213\\setup\\specifs2\\objets/WMRSTABU.DHOQ (erreur 20),
"LectureFichier":"//psxbdjpt01/divalto/erp213/fichiers/implicitesdemo.xml",
"ImplicitesLocales":"//psxbdjpt01/divalto/erp213/fichiers/implicitesdemo.txt",
"LectureFichier":"c:\divalto\erp213\fichiers\connexions.xml",
"ConnexionsLocales":"c:\divalto\erp213\fichiers\connexions.xml",
"cheminxlogfenv":"//PSXBDJPT01/Divalto/ERP213/fichiers",
"cheminxlogf":"//psxbdjpt01/divalto/erp213/fichiers",
"CheminDivalto":"c:\Divalto",
"CheminEtFichierImplicites":"//psxbdjpt01/divalto/erp213/fichiers/implicitesdemo.txt",
"CheminEtFichierImplicitesOpen":"//psxbdjpt01/divalto/erp213/fichiers/implicitesdemo.txt",
"CheminEtFichierImplicitesAuformatWindows":"c:\divalto\erp213\fichiers\implicitesdemo.txt",
"LectureFichier":"A5RSDOS.DHOQ",
"LectureFichier":"A5RSDOS.DHOQ",
"objetdhoq":"A5RSDOS.DHOQ",
"LectureFichier":"//psxbdjpt01/divalto/erp213/fichiers/implicitesdemo.xml",
"ImplicitesLocales":"//psxbdjpt01/divalto/erp213/fichiers/implicitesdemo.txt",
"LectureFichier":"c:\divalto\erp213\fichiers\connexions.xml",
"ConnexionsLocales":"c:\divalto\erp213\fichiers\connexions.xml",
"cheminxlogfenv":"//PSXBDJPT01/Divalto/ERP213/fichiers",
"cheminxlogf":"//psxbdjpt01/divalto/erp213/fichiers","CheminDivalto":"c:\Divalto",
"CheminEtFichierImplicites":"//psxbdjpt01/divalto/erp213/fichiers/implicitesdemo.txt",
"CheminEtFichierImplicitesOpen":"//psxbdjpt01/divalto/erp213/fichiers/implicitesdemo.txt",
"CheminEtFichierImplicitesAuformatWindows":"c:\divalto\erp213\fichiers\implicitesdemo.txt",
….
"cheminxlogfenv":"//PSXBDJPT01/Divalto/ERP213/fichiers",
"cheminxlogf":"//psxbdjpt01/divalto/erp213/fichiers",
"CheminDivalto":"c:\Divalto",
"CheminEtFichierImplicites":"//psxbdjpt01/divalto/erp213/fichiers/implicitesdemo.txt",
"CheminEtFichierImplicitesOpen":"//psxbdjpt01/divalto/erp213/fichiers/implicitesdemo.txt",
"CheminEtFichierImplicitesAuformatWindows":"c:\divalto\erp213\fichiers\implicitesdemo.txt",
"CheminEtFichierImplicitesAuformatWindows":"c:\divalto\erp213\fichiers\implicitesdemo.txt","LectureFichier":"GTRSDOS.DHOQ",
"LectureFichier":"GTRSDOS.DHOQ",
"objetdhoq":"GTRSDOS.DHOQ",
"addon ErreurLectureFichier":\divalto\erp213\setup\specifs\objets\GTRSDOSU.DHOQ (erreur 20),
"addon ErreurLectureFichier": \divalto\erp213\setup\specifs2\objets\GTRSDOSU.DHOQ (erreur 20),
"LectureFichier":"//psxbdjpt01/divalto/erp213/fichiers/implicitesdemo.xml",
"ImplicitesLocales":"//psxbdjpt01/divalto/erp213/fichiers/implicitesdemo.txt",
"LectureFichier":"c:\divalto\erp213\fichiers\connexions.xml",
"ConnexionsLocales":"c:\divalto\erp213\fichiers\connexions.xml"}}"
Demande

Demandes spéciales (cache, dhoq)

La balise dhoq accepte des mot clés pour demandes spéciales

_razcache

permet d’effacer le cache des dictionnaires et des dhoq etc. Cela permet d’obliger le module REST à tout recharger, par exemple si on a fait des modifications importantes dans des dhoq.

Par défaut, le module REST met a jour les objets du cache s'ils ont plus de 10 minutes d’ancienneté, cette commande permet de le faire immédiatement

_razuser

permet d’effacer le cache qui contient les informations de l’utilisateur en cours.

Par défaut , le module REST met les informations qu’il lit de l’utilisateur dans un cache, ces informations sont actualisées automatiquement au bout de 10 minutes, cette commande permet de le faire immédiatement

_razautorisedhoq

permet d’effacer le cache des fichiers paramètres xml, et en particulier celui qui contient la liste des dhoq autorisés.

Par défaut, le module REST actualise ce cache toute les 10 minutes, cette commande permet de le faire immédiatement

Informations complémentaires : gestion de la pagination

Le service web est configuré pour renvoyer un nombre maximal d'enregistrements (par défaut 1000, mais peut être inférieur).

Il est donc conseillé, lorsqu'une requête de lecture est susceptible de renvoyer beaucoup d'enregistrements, d'utiliser la pagination pour récupérer les enregistrements par lots.

Deux paramètres d'appels vont servir :

  • count

  • offset

et une donnée de retour va servir :

  • nbrecord

Le premier appel devra se fait avec un offset à 0 et un count dimensionné selon le nombre d'enregistrements d'un lot, par exemple 10.

La réponse au premier appel donne les 'nbrecord' premier enregistrements.

Si 'nbrecord' est égal a count, alors il y a une suite. L'appel suivant devra reprendre les 'nbrecord' en plus dans l'offset pour interroger les suivants. Le count conserve sa valeur du premier appel.

Sinon (donc 'nbrecord' est inférieur a count), alors tout a été lu

Exemple en 2 pages de 10 pour un total de 18 enregistrements
Bloc de code
Premier appel : OFFSET=0                   COUNT=10
Réponse : 10 enregistrements et NBRECORD=10
NBRECORD est égal à COUNT donc il y a une suite

Second appel : OFFSET=OFFSET+NBRECORD=10   COUNT=10
Réponse : 8 enregistrements et NBRECORD=8
NBRECORD est inférieur à COUNT c'est terminé

Exemple en 3 pages de 5 pour un total de 15 enregistrements
Bloc de code
Premier appel : OFFSET=0                      COUNT=5
Réponse : 5 enregistrements et NBRECORD=5
NBRECORD est égal à COUNT donc il y a une suite

Second appel : OFFSET=OFFSET+NBRECORD=5       COUNT=5
Réponse : 5 enregistrements et NBRECORD=5
NBRECORD est égal à COUNT donc il y a une suite

Troisième appel : OFFSET=OFFSET+NBRECORD=10   COUNT=5
Réponse : 5 enregistrements et NBRECORD=5
NBRECORD est égal à COUNT donc il y a une suite

Quatrième appel : OFFSET=OFFSET+NBRECORD=15   COUNT=5
Réponse : 0 enregistrements et NBRECORD=0
NBRECORD est inférieur à COUNT c'est terminé

Exemple de programmation
Bloc de code
int woffset = 0
int mycount = 10
int fini = 0

while ( fini = 0 )
{
	;requete rest rsql avec  {offset=woffset    count= mycount }
	;traiter le resultat, dont en retour le nbrecord

	if ( nbrecord < mycount )
		fini = 1					;plus de suite
	else
		woffset = woffset + mycount	;on lit la suite
}

Astuce

Le mécanisme de pagination se repose strictement sur la pagination SQL Server. Chaque appel déclenche donc une requête différente, sans cache ni curseur, avec les éventuelles modification de données effectuées entre chaque appel.

Consultez l'aide Microsoft SQL Server pour plus d'informations

Format de la réponse

Le service web RecordSql REST répond a une demande de lecture de données sous une forme JSON avec les résultats suivants:

Balise

Description

"error"

Contient le CODE ERREUR

  • 0 signifie qu'il n'y a pas d'erreur

  • tout autre valeur indique une erreur

Retrouvez dans cette page les code retour d’erreur

"txterr"

Texte de l'erreur, si applicable

"tablename"

Nom de la table FROM lue

"nbrecord"

Nombre d'enregistrements retournés

"records"

Tableau avec les enregistrements retournés

"infos"

Informations générales ou performance

Le champs 'infos', dans le cas d'une demande d'information de performance, peut contenir plusieurs informations indiquant des temps d'exécution.

Exemples : "{\"xperf\" : {\"ExecuteRequestSQL\" : \"0\",\"LoadUser\" : \"1\",\"LoadDHXISAM\" : \"15\",\"LoadRecordForSQL\" : \"1\",\"LoadDataForSQL\" : \"1\",\"ImpersonationSQL\" : \"1\",\"ExecuteSQL\" : \"1\",\"ResultSQL\" : \"3\" }}"

Info

Information technique

  • Les valeurs retournées ne sont pas traduites

  • Les montants sont toujours avec un point comme séparateur de décimales

  • Les dates sont au format 'AAAAMMJJ'

Dans les exemples suivants, xxxxxx pour 'access_token' est a remplacer par la valeur du token obtenue lors de l'authentification.

Comment trouver le recordSql a utiliser

Infinity se repose sur les recordSql pour l'accès aux données de la base de données.

Quelques définitions d'un recordSql:

  • porte un nom (en clair, en français), par exemple Article

  • fait partie d'un ensemble (codifié) : le dictionnaire de recordSql, par exemple gtrsart.dhoq

    • xxRSyyyy.DHOQ : xx correspond au module (par exemple GT pour la gestion commerciale) et yyyy a une famille (par exemple art pour la famille articles)

  • assemble tous les composants d'une requête SQL

    • la table principale (celle du FROM)

    • les champs (du FROM, champs calculés et champs des jointures)

    • les conditions (WHERE, HAVING, COUNT)

    • les tris

Avertissement

Pour trouver le nom du dictionnaire, du recordsql, des clauses where, etc...il faut nécessairement trouver le fichier source correspondant xxRSyyyy.DHSP , et l'ouvrir avec Harmony SDK ou a défaut un bloc-notes

La moyen le plus simple de trouver une table courante est d'utiliser le zoom correspondant.

Avec le menu Aide / A propos, la fenêtre indique des informations

Exemple : zoom article

 

On y trouve le nom du recordSql et on peut y trouver une indication sur le module.

Exemple : recordSql Article   module GT

=>notre recordSql se trouve dans GTRSART.DHSP et s'appelle Article

et on y trouvera plus bas les jointures, clauses where et tris.

 

Une fois identifié, l'utilitaire Harmony XRecordSQLCheck.exe (a lancer depuis /divalto/sys) permet de manipuler le recordSql et de le tester avant de l'utiliser dans un service web

Le bas de l'écran contient la requête SQL générée, qui peut être copiée dans un éditeur de requêtes SQL, par exemple Sql Management Studio

Exemples

Lecture en échec

Exemple de demande de lecture de la table de codes postaux, alors que le paramétrage des RecordSql n'est pas fait :

{
"dhoq" : "xxrstab.dhoq",
"recordsql" : "",
"access_token" : "xxxxxx",
"parameters" : " ",
"fields" : "*",         
"where" : " ",
"where_parameters" : " ",
"offset" : 0,
"count" : 0,
"orderby" :  " ",
"havingc" : " ",
"having_parameters" : " ",
"infos" : " " 
}

Réponse :

{
    "error": 54,
    "txterr": "erreur : dhoq '' non autorisé",
    "tablename": "",
    "nbrecord": 0,
    "records": null,
    "infos": ""
}

Lecture simple

Exemple de demande de lecture de la table de catégories fournisseur, sans conditions ni champs précisés :

{
"dhoq" : "gtrstab.dhoq",
"recordsql" : "CATFOU",
"access_token" : "xxxxxx",
"parameters" : " ",
"fields" : "",          
"where" : " ",
"where_parameters" : " ",
"offset" : 0,
"count" : 0,
"orderby" :  " ",
"havingc" : " ",
"having_parameters" : " ",
"infos" : " " 
}

Réponse (a noter que la demande en count=0 donne un retour nbrecord=1:

{
    "error": 0,
    "txterr": "",
    "tablename": "T116",
    "nbrecord": 1,
    "records": [
        {
            "record": {
                "T116_ID": "3",
                "CEBIN": "116",
                "DOS": "998",
                "TABNO": "116",
                "CATFOUCOD": "TRANSIT",
                "LIB80": "Transitaire",
                "CATFABFL": "1",
                "USERCR": "DEMO",
                "USERMO": "DEMO",
                "USERCRDH": "20191119144005",
                "USERMODH": "20191119144026",
                "CENOTE": "1",
                "NOTE": "0"
            }
        }
    ],
    "infos": ""
}

Exemple de demande de lecture de la table de codes postaux, sans conditions mais avec liste de champs ET uniquement les 2 premiers:

{
"dhoq" : "gtrstab.dhoq",
"recordsql" : "CODEPOSTAL",
"access_token" : "xxxxxx",
"parameters" : " ",
"fields" : "CPOSTAL;VIL",           
"where" : " ",
"where_parameters" : " ",
"offset" : 0,
"count" : 100,
"orderby" :  " ",
"havingc" : " ",
"having_parameters" : " ",
"infos" : " " 
}

Réponse :

{
    "error": 0,
    "txterr": "",
    "tablename": "T057",
    "nbrecord": 2,
    "records": [
        {
            "record": {
                "CPOSTAL": "01000",
                "VIL": "BOURG EN BRESSE"
            }
        },
        {
            "record": {
                "CPOSTAL": "01000",
                "VIL": "BROU"
            }
        }
    ],
    "infos": ""
}

Lecture simple avec conditions

Exemple de demande de lecture de la table de codes postaux, avec conditions LIKE et liste de champs :

{

"dhoq":"gtrstab.dhoq",
"recordsql":"CODEPOSTAL",
"access_token":"xxxxxx",
"parameters":"",
"fields":"CPOSTAL;VIL",
"where":"like_cpostal",
"where_parameters":"cpostal=67%",
"offset":0,
"count":100,
"orderby":"",
"having":"",
"having_parameters":"",
"infos":""
}

Réponse :

{
    "error": 0,
    "txterr": "",
    "tablename": "T057",
    "nbrecord": 1,
    "records": [
        {
            "record": {
                "CPOSTAL": "67000",
                "VIL": "STRASBOURG"
            }
        }
    ],
    "infos": ""
}

Lecture avec pagination

Exemple de demande de lecture de la table des modes de règlement avec pagination par 10 : Première lecture

{
"dhoq" : "gtrstab.dhoq",
"recordsql" : "MODEREGLEMENT",
"access_token" : "xxxxxx",
"parameters" : " ",
"fields" : "*",         
"where" : " ",
"where_parameters" : " ",
"offset" : 0,
"count" : 10,
"orderby" :  " ",
"having" : " ",
"having_parameters" : " ",
"infos" : " " 
}

Réponse :

{
    "error": 0,
    "txterr": "",
    "tablename": "T006",
    "nbrecord": 10,
    "records": [
        {
            "record": {
                "DOS": "998",
                "REGL": "B30",
                "LIB": ""
            }
        },
        {
            "record": {
                "DOS": "998",
                "REGL": "B30F",
                "LIB": ""
            }
        },
        {
            "record": {
                "DOS": "998",
                "REGL": "C",
                "LIB": ""
            }
        },
        {
            "record": {
                "DOS": "998",
                "REGL": "N10",
                "LIB": ""
            }
        },
        {
            "record": {
                "DOS": "998",
                "REGL": "N30",
                "LIB": ""
            }
        },
        {
            "record": {
                "DOS": "998",
                "REGL": "P30",
                "LIB": ""
            }
        },
        {
            "record": {
                "DOS": "998",
                "REGL": "P30F",
                "LIB": ""
            }
        },
        {
            "record": {
                "DOS": "998",
                "REGL": "T30",
                "LIB": ""
            }
        },
        {
            "record": {
                "DOS": "998",
                "REGL": "T30F",
                "LIB": ""
            }
        },
        {
            "record": {
                "DOS": "998",
                "REGL": "T60",
                "LIB": ""
            }
        }
    ],
    "infos": ""
}

La réponse indique un NBRECORD qui vaut le COUNT demandé, donc il faut une seconde lecture:

{
"dhoq" : "gtrstab.dhoq",
"recordsql" : "MODEREGLEMENT",
"access_token" : "xxxxxx",
"parameters" : "",
"fields" : "DOS;REGL;LIB",          
"where" : " ",
"where_parameters" : " ",
"offset" : 10,
"count" : 10,
"orderby" :  " ",
"havingc" : " ",
"having_parameters" : " ",
"infos" : " " 
}

Réponse :

{
    "error": 0,
    "txterr": "",
    "tablename": "T006",
    "nbrecord": 9,
    "records": [
        {
            "record": {
                "DOS": "998",
                "REGL": "T60F",
                "LIB": ""
            }
        },
        {
            "record": {
                "DOS": "998",
                "REGL": "TMUL",
                "LIB": ""
            }
        },
        {
            "record": {
                "DOS": "998",
                "REGL": "V30",
                "LIB": ""
            }
        },
        {
            "record": {
                "DOS": "998",
                "REGL": "V30F",
                "LIB": ""
            }
        },
        {
            "record": {
                "DOS": "998",
                "REGL": "E",
                "LIB": ""
            }
        },
        {
            "record": {
                "DOS": "998",
                "REGL": "TMEN",
                "LIB": ""
            }
        },
        {
            "record": {
                "DOS": "998",
                "REGL": "VIR",
                "LIB": ""
            }
        },
        {
            "record": {
                "DOS": "998",
                "REGL": "VII",
                "LIB": ""
            }
        },
        {
            "record": {
                "DOS": "998",
                "REGL": "SEPA",
                "LIB": ""
            }
        }
    ],
    "infos": ""
}

La réponse indique un NBRECORD différent de COUNT, donc c'est terminé

Lecture avec champs, clause where join et orderby

Exemple de demande de lecture de la table des articles pour une plage de code ean, trié par ean, en récupérant 3 champs, sans jointures et sans autres colonnes

{
"dhoq" : "gtrsart.dhoq",
"recordsql" : "ARTICLE",
"access_token" : "xxxxxx",
"parameters" : "",
"fields" : "DOS;REF;EAN",           
"where" : "Between_Ean",
"where_parameters" : "eanD=3000000000000;eanF=4000000000000",
"offset" : 0,
"count" : 5,
"orderby" :  "Par_CodeEAN",
"having" : " ",
"having_parameters" : " ",
"infos" : "<joindeactivate>$ALL<columndeactivate>$ALL" 
}

Réponse :

{
    "error": 0,
    "txterr": "",
    "tablename": "ART",
    "nbrecord": 5,
    "records": [
        {
            "record": {
                "DOS": "998",
                "REF": "FCR0011",
                "EAN": "3210330000250"
            }
        },
        {
            "record": {
                "DOS": "998",
                "REF": "CPAQ0009",
                "EAN": "3210330003821"
            }
        },
        {
            "record": {
                "DOS": "998",
                "REF": "FPN0104",
                "EAN": "3210330017159"
            }
        },
        {
            "record": {
                "DOS": "998",
                "REF": "X0000018",
                "EAN": "3210330017585"
            }
        },
        {
            "record": {
                "DOS": "998",
                "REF": "FPT0061",
                "EAN": "3210330021356"
            }
        }
    ],
    "infos": ""
}

Interrogation token

Exemple de demande d’informations concernant le token

{
"dhoq" : "a5rsdos.dhoq",
"recordsql" : "Utilisateur",
"access_token" : "{{TOKEN}}",
"infos" : "<infostoken>1" 
}

Réponse :

{
"error": 0,
"txterr": "",
"tablename": "MUSER",
"nbrecord": 1,
"records": [
],
"infos": "{\"InfosToken\":{\"ExpireLocalTime\":\"20230314174105\",\"ExpireUtcTime\":\"20230314164105\",\"ExpireMinutes\":\"0\",\"ExpireLocalTimeName\":\"Romance Standard Time\",\"Env\":\"\",\"User\":\"\",\"Domain\":\"\"}}"
}

Sommaire
maxLevel3
minLevel1
classd-toc-article