/* SQL.ULH (STD) -- User Language SQL Utilities */ /* SQL.ULH (STD) -- User Language SQL-Utilities */ /* // Copyright (c) 1994-2012 Oliver Bartels F+E, Muenchen // Author: Manfred Baumeister // Changes History: // rl (120427) RELEASED FOR BAE V7.8. // rl (101019) RELEASED FOR BAE V7.6. // rl (091020) RELEASED FOR BAE V7.4. // rl (081014) RELEASED FOR BAE V7.2. // rl (071029) RELEASED FOR BAE V7.0. // rl (060829) RELEASED FOR BAE V6.8. // rl (060623) ENHANCEMENT: // New function sql_lockcheck implemented. // rl (050912) RELEASED FOR BAE V6.6. // rl (050912) ENHANCEMENT: // New function sql_quotestr implemented. // rl (040811) RELEASED FOR BAE V6.4. // rl (030904) RELEASED FOR BAE V6.2. // rl (021209) RELEASED FOR BAE V6.0. // rl (020618) RELEASED FOR BAE V5.4. // rl (010625) RELEASED FOR BAE V5.0. // rl (000509) RELEASED FOR BAE V4.6. // rl (990625) RELEASED FOR BAE V4.4. // rl (980910) RELEASED FOR BAE V4.2. // mb (980710) ENHANCEMENT: // Dynamic multi-language support introduced. // rl (971103) ENHANCEMENT: // New functions sql_cmptabs, sql_createtab implemented. // rl (970929) RELEASED FOR BAE V4.0. // mb (970327) CHANGE: // Inline documentation changed; source re-formatted. // mb (961119) ENHANCEMENT: // New functions sql_dtyp2str, sql_getfields, sql_gettabs // implemented. // mb (961119) CHANGE: // Function dberror renamed/replaced by sql_dberror. // mb (960917) RELEASED FOR BAE V3.4. // mb (95) RELEASED FOR BAE V3.2. // mb (94) RELEASED FOR BAE V3.0. // mb (94) ORIGINAL CODING. // // DESCRIPTION // // The definitions and declarations from include file sql.ulh are // compatible with all User Language interpreter environments of // the Bartels AutoEngineer (i.e. Schematic Editor, Layout Editor, // Autoplacement, Neural Autorouter, CAM Processor, CAM View, and // Chip Editor, respectively). sql.ulh provides a series of useful // SQL database management utilities. // // FUNCTIONS // // Message and error handling: // sql_dberror -- Issue SQL/database error and end program on error // // Data conversion: // sql_dtyp2str -- Convert SQL data type to string/name // sql_quotestr -- Single/double quote string depending on string content // // Lock database query: // sql_lockcheck -- Check project element locks by other users // // Listview column width database utilities: // sql_lv_init -- Initialise the listview column width database // sql_lv_getwidth -- Query listview column width // sql_lv_storewidth -- Store listview column width // // SQL database/query: // sql_cmptabs -- Compare two SQL tables // sql_createtab -- Create a SQL table // sql_getdata -- Get field data of specific SQL table // sql_getfields -- Get field definitions of specific SQL table // sql_gettabs -- Get SQL table names stored to specific SQL/DB file */ // Avoid multiple inclusion #ifndef INCLUDE_SQL #define INCLUDE_SQL // Includes #include "std.ulh" // User Language standard include // SQL data type values #define SQLNONE (-1) // Unknown/invalid SQL data type #define SQLINT 2 // Integer data type #define SQLDBL 3 // Double data type #define SQLSTR 4 // String data type #define SQLDATE 5 // Date data type #define SQLBOOL 6 // Boolean data type // Data types typedef STRINGS STRTAB[]; // String table type typedef struct { // Table field descriptor string fname; // Table field name int fdtyp; // Table field data type int ml; // Max. table field entry length } sql_field; // Table field type typedef sql_field sql_fields[]; // Table field list type // SQL data type names #define SQL_DTYPINT "INTEGER" #define SQL_DTYPDBL "FLOAT" #define SQL_DTYPSTR "STRING" #define SQL_DTYPDATE "DATE" #define SQL_DTYPBOOL "BOOLEAN" #define SQL_DTYPILL "illegal" //__________________________________________________________________ // Start library-specific source code #ifndef USELIB #ifndef LIBSQL // SQL command strings #define CMD_GETTABS "help;" #define CMD_GETFIELDS "help %s;" #define CMD_GETDATA "select from %s;" #define CMD_CREATETABH "create table %s (" #define CMD_CREATETABT ");" // SQL lock query command strings #define L_SELECT1 "select username,ename,mode from lockinfo" #define L_SELECT2 " where class=%d AND ename=%s;" #define L_SELECT2P " where class=%d AND ename LIKE '%%';" // SQL Listview column width table command strings #define W_HELP "help lvhead;" #define W_CREATE1 "create table lvhead (colhead string," #define W_CREATE2 "colidx integer,colwidth float);" #define W_INSERT "insert into lvhead values(%s,%d,%.2f);" #define W_SELECT "select colwidth from lvhead where colhead=%s AND colidx=%d;" #define W_DELETE "delete from lvhead where colhead=%s;" // INI file parameter name definitions #define PAR_LOCKMODE "LOCKMODE_STD" // Element lock mode #define PAR_LOCKEXT "LOCKEXT_STD" // Lock file extension // Globals static STRINGS curtabl; // Current table name list static int curtabn; // Current table count static sql_fields curfieldl; // Current field list static int curfieldn = 0; // Current field count static sql_fields IFIELDL = { // Field list initialyzer {"",SQLNONE,0} }; static STRINGS curtabentry; // Current table entry string list static STRTAB curetab; // Current entry/string table static int curen; // Current entry count static string sqllockuser /* Lock user name */; static string maxlockuser /* Max. lock user name */; static string sqllockename /* Locked element name */; static string maxlockename /* Max. locked element name */; static string sqllockexclude /* Lock exclude element name */; static int maxlockmode /* Max. data lock mode */; static int sqllockfound /* Data lock found flag */; static double sqllvwidth /* Listview column width */; // List initialyzers #ifndef LISTINIT #define LISTINIT static STRINGS ISTRL = {""}; // String list initialyzer static STRTAB ISTRTAB = {ISTRL}; // String table initialyzer #endif //__________________________________________________________________ // Error handling void sql_dberror(int igncode) /* // Issue (current) SQL/database error and end program on error // Parameters : // int igncode : Ignorable error code */ { // Messages string ERRPREFIX = M("(SQL) ","(SQL) "); STRINGS SQLERRS = { /* 0 */ M("Kein Fehler.","No error."), /* 1 */ M("Kommando Lesefehler (intern)!", "Command read error (internal)!"), /* 2 */ M("Kommandoeingabe Ausdruck zu komplex!", "Command input expression too complex!"), /* 3 */ M("Ungueltiger numerischer Ausdruck!", "Invalid numerical expression!"), /* 4 */ M("Kommandoeingabe nicht gefunden!", "Command input not found!"), /* 5 */ M("Kommandoeingabe Element zu lang!", "Command input element too long!"), /* 6 */ M("Syntaxfehler bei '%s'!","Syntax error at '%s'!"), /* 7 */ M("Allgemeiner Kommando-Parser-Fehler!", "General command parser failure!"), /* 8 */ M("Dateianlage fehlgeschlagen!","File creation failed!"), /* 9 */ M("Dateizugriff fehlgeschlagen!","File access failed!"), /* 10 */M("Zu viele offene Dateien im System!", "Too many open files in system!"), /* 11 */M("Datei '%s' ist keine Datenbank!", "File '%s' isn't a database!"), /* 12 */M("Die Datenbankstruktur ist beschaedigt!", "File structure damaged!"), /* 13 */M("Der Dateiaufbau ist fehlerhaft!", "File data structure invalid!"), /* 14 */M("Key '%s' nicht gefunden!","Key '%s' not found!"), /* 15 */M("Key '%s' existiert bereits!","Key '%s' already defined!"), /* 16 */M("Datei '%s' nicht gefunden!","File '%s' not found!"), /* 17 */M("Tabelleneintrag fuer '%s' vom falschen Typ!", "Table entry for '%s' has wrong type!"), /* 18 */M("Eintrag hat mehr Elemente als in Tabelle '%s' definiert!", "Entry has more elements than defined in table '%s'!"), /* 19 */M("Eintraglaenge ueber Datenbanklimit!", "Entry length exceeds database limit!"), /* 20 */M("Bedingte Loeschung nur fur eine Tabelle erlaubt!", "Conditional delete allowed for only one table!"), /* 21 */M("Ungueltige Typkombination in Term/Vergleich!", "Invalid type combination in term/comparison!"), /* 22 */M("Ausgabefeld '%s' nicht in Tabelle(n)!", "Output field '%s' not in table(s)!"), /* 23 */M("Ausgabefeld '%s' in mehreren Tabellen vorhanden!", "Output field '%s' defined in more than one table!"), /* 24 */M("Ausgabetabelle '%s' nicht in from Tabellenliste!", "Output table '%s' not in from tablelist!"), /* 25 */M("Tabelle '%s' bereits vorhanden!", "Table '%s' already defined!"), /* 26 */M("Datenbank Eintraglimit ueberschritten!", "Database entry limit exceeded!"), /* 27 */M("Tabelle '%s' nicht gefunden!","Table '%s' not found!"), /* 28 */M("Fehler in Rueckgabefunktion!", "Error in callback function!"), /* 29 */M("Kein delete-Record gefunden!","No delete record found!"), /* 30 */M("Unbekanntes/neueres Datenbankformat!", "Unknown/new database format!"), /* 31 */M("Abfragefeld '%s' nicht in Tabelle(n)!", "Query field '%s' not in table(s)!"), /* 32 */M("Abfragefeld '%s' in mehreren Tabellen vorhanden!", "Query field '%s' defined in more than one table!"), /* 33 */M("Datei '%s' Lesezugriff nicht erlaubt!", "File '%s' read access not allowed!"), /* 34 */M("Datei '%s' ist schreibgeschuetzt!", "File '%s' is read only!"), M("Allgemeiner Datenbankfehler / SQL/DB-Datei korrupt!", "General database failure / SQL/DB file corrupt!") }; int errcode; // Database error code int dispmode; // Error display mode string erritem; // Database error item string errstr; // Database error string string errmsg; // Database error message string // Get the error code and error item string sqlerr(errcode,erritem); // Abort if ignorable error code if (errcode==igncode || errcode==0) return; // Get error format/message if ((errstr=SQLERRS[errcode])=="") errstr=SQLERRS[arylength(SQLERRS)-1]; // Display the error message sprintf(errmsg,errstr,erritem); error(ERRPREFIX+errmsg); // Check if extra dialog box display bae_getintpar(37,dispmode); if (dispmode) bae_msgbox(3,ERRPREFIX+errmsg,""); } //__________________________________________________________________ // Data conversion string sql_dtyp2str(int dtype) /* // Convert SQL data type to string/name // Return value : // SQL data type name // Parameters : // int dtype : SQL data type to be converted */ { // Evaluate the data type; return the data type name switch (dtype) { case SQLINT : return(SQL_DTYPINT); // Integer case SQLDBL : return(SQL_DTYPDBL); // Double case SQLSTR : return(SQL_DTYPSTR); // String case SQLDATE : return(SQL_DTYPDATE); // Date case SQLBOOL : return(SQL_DTYPBOOL); // Boolean } // Assume unknown/invalid SQL data type return(SQL_DTYPILL); } string sql_quotestr(string str) /* // Single/double quote string depending on string content // Return value : // Quoted string // Parameters : // int str : Data string */ { return(strscannext(str,"'",0,1)>strlen(str) ? ("'"+str+"'") : ("\""+str+"\"") ); } //__________________________________________________________________ // SQL lock database query int sql_lockcheck(string fname,string ename,int ddbcl,string username) /* // Check element lock of given element(s) // Return values : // 0 - no lock // 1 - lock warning // 2 - lock warning, save disabled // 3 - element locked // Parameters : // string fname : Project file name // string ename : Element name, * for any with 1st returned // int ddbcl : Element class // string username : Lock user name return */ { string sqlcmdstr; // SQL command string int lockmode = bae_iniintval(PAR_LOCKMODE,0) /* Element lock mode */; string lockext = bae_inistrval(PAR_LOCKEXT,".lck") /* Lock file name extension */; string lockfname /* Lock database file name */; // Disable lock check for currently loaded element sqllockexclude= (fname==bae_planfname() && (ename=="*" || ename==bae_planename()) && ddbcl==bae_planddbclass()) ? bae_planename() : "" ; // Check if element locked by other user sqllockfound=0; lockfname=convstring(fname,0)+lockext; if (ename=="*") sprintf(sqlcmdstr,L_SELECT1+L_SELECT2P,ddbcl); else sprintf(sqlcmdstr,L_SELECT1+L_SELECT2,ddbcl, sql_quotestr(ename)); sqlcmd(lockfname,sqlcmdstr,sqllockchkfunc); if (sqllockfound) { // Use more restrictive mode if (lockmode>maxlockmode) maxlockmode=lockmode; // Return element and user name ename=maxlockename; username=maxlockuser; return(maxlockmode); } // No lock found return(0); } static int sqllockchkfunc(string dstr,int dint,double ddbl, int dval,int dtype,string dtable,string dfield,int didx) /* // Macro selection callback function // Return value : // zero if done or (-1) on data error // Parameters : // string dstr : String/Date data // int dint : Integer/Boolean data // double ddbl : Float data // int dval : Data valid flag // int dtype : Data type // string dtable : Data table name // string dfield : Data field name // int didx : Data output field index */ { switch (didx) { // User name case 1 : sqllockuser=dstr; break; // Element name case 2 : sqllockename=dstr; break; // Lock mode case 3 : if ((!sqllockfound || dint>maxlockmode || (dint==maxlockmode && sqllockuser=="")) && sqllockename!=sqllockexclude) { maxlockuser=sqllockuser; maxlockename=sqllockename; maxlockmode=dint; sqllockfound=1; } break; } // Return without errors return(0); } //__________________________________________________________________ // SQL Listview database utilities void sql_lv_init() /* // Initialize the listview column width database */ { string ERRDBINIT = M("SQL/DB-Datei '%s' kann nicht initialisiert werden!", "Error initialyzing SQL/DB file '%s'!"); string WPOSDB = strgetconffilename(WPOSVARNAME,WPOSFILENAME,2); // Create/init column width info database file if (sqlinit(WPOSDB,0)==(-1) && sqlinit(WPOSDB,1)==(-1)) // SQL/DB creation error errormsg(ERRDBINIT,WPOSDB); // Check if table alreade defined if (sqlcmd(WPOSDB,W_HELP,NULL)!=0) // Create the table if (sqlcmd(WPOSDB,W_CREATE1+W_CREATE2,NULL)) // SQL/DB error (ignore table defined error) sql_dberror(25); } double sql_lv_getwidth(string tabspec,int colidx,double defwidth) /* // Query listview column width // Return value : // column width // Parameters : // string tabspec : Table specification string // int colidx : Column index // double defwidth : Column default width */ { string WPOSDB = strgetconffilename(WPOSVARNAME,WPOSFILENAME,2); string sqlcmdstr; // SQL command string sqllvwidth=defwidth; sprintf(sqlcmdstr,W_SELECT,sql_quotestr(tabspec),colidx); if (sqlcmd(WPOSDB,sqlcmdstr,sqlcolwfunc)!=0) sql_dberror(0); return(sqllvwidth); } void sql_lv_storewidth(string tabspec,int lvidx,int colidx) /* // Store listview column width // Parameters : // string tabspec : Table specification string // int lvidx : Listview control base index // int colidx : Column index */ { string WPOSDB = strgetconffilename(WPOSVARNAME,WPOSFILENAME,2); string sqlcmdstr; // SQL command string double w; // Column width bae_dialgetdata(lvidx+1+colidx,0,w,""); sprintf(sqlcmdstr,W_INSERT,sql_quotestr(tabspec),colidx,w); if (sqlcmd(WPOSDB,sqlcmdstr,NULL)!=0) // SQL/DB error sql_dberror(0); } static int sqlcolwfunc(string dstr,int dint,double ddbl, int dval,int dtype,string dtable,string dfield,int didx) /* // Column width query callback function // Return value : // zero if done or (-1) on data error // Parameters : // string dstr : String/Date data // int dint : Integer/Boolean data // double ddbl : Float data // int dval : Data valid flag // int dtype : Data type // string dtable : Data table name // string dfield : Data field name // int didx : Data output field index */ { sqllvwidth=ddbl; // Return without errors return(0); } //__________________________________________________________________ // SQL database/query int sql_gettabs(string sqlfname,STRINGS tabs) /* // Get SQL table names stored to specific SQL/DB file // Return value : // number of tables found or (-1) on SQL/DB file access failure // Parameters : // string sqlfname : SQL/DB file name // STRINGS tabs : SQL table name list */ { // Init the current table name list curtabn=0; curtabl=ISTRL; // Get table names if (sqlcmd(sqlfname,CMD_GETTABS,tabnamefunc)!=0) // SQL error return(-1); // Store the table name list tabs=curtabl; // Return the table count return(curtabn); } int sql_getfields(string sqlfname,string tabname,sql_fields fields) /* // Get field definitions of specific SQL table // Return value : // number of table fields found or (-1) on SQL/DB file access failure // Parameters : // string sqlfname : SQL/DB file name // string tabname : SQL table name // sql_fields fields : SQL table field list */ { string sqlcmdstr; // SQL command string // Init the current table field list curfieldn=0; curfieldl=fields=IFIELDL; // Get the table field definitions sprintf(sqlcmdstr,CMD_GETFIELDS,tabname); if (sqlcmd(sqlfname,sqlcmdstr,tabfieldfunc)!=0) // SQL error return(-1); // Store the table field list fields=curfieldl; // Return the table field count return(curfieldn); } int sql_getdata(string sqlfname,string tabname,STRTAB tabdata) /* // Get SQL table data // Return value : // number of table entries found or (-1) on SQL/DB file access failure // Parameters : // string sqlfname : SQL database file name // string tabname : SQL table name // STRTAB tabdata : SQL data/string table */ { string sqlcmdstr; // SQL command string // Get the table field definitions if ((curfieldn=sql_getfields(sqlfname,tabname,curfieldl))<0) // SQL error return(-1); // Clear the entry list curetab=ISTRTAB; curen=0; // Select data entries from database table sprintf(sqlcmdstr,CMD_GETDATA,tabname); sqlcmd(sqlfname,sqlcmdstr,tabdatafunc); // Store the table data tabdata=curetab; curetab=ISTRTAB; // Return the table entry count return(curen); } int sql_cmptabs(sql_fields fields1,sql_fields fields2) /* // Compare two SQL table field definitions // Return value : // zero if equal, one if not equal // Parameters : // sql_fields fields : SQL table field list */ { int len; // Field length int i; // Loop control variable // Check if same length fields if ((len=arylength(fields1))!=arylength(fields2)) // Different element count -> different tables return(1); // Compare all table entries for (i=0;i0;i--) if (curtabl[i-1]>dtable) curtabl[i]=curtabl[i-1]; else break; curtabl[i]=dtable; curtabn++; // Return without errors return(0); } static int tabfieldfunc(string dstr,int dint,double ddbl, int dval,int dtype,string dtable,string dfield,int didx) /* // Table structure/field callback function // Return value : // zero if done or (-1) on data error // Parameters : // string dstr : String/Date data // int dint : Integer/Boolean data // double ddbl : Float data // int dval : Data valid flag // int dtype : Data type // string dtable : Data table name // string dfield : Data field name // int didx : Data output field index */ { // Store new field entry curfieldl[didx-1].fname=dfield; curfieldl[didx-1].fdtyp=dtype; curfieldl[didx-1].ml=maxint(strlen(dfield), strlen(sql_dtyp2str(curfieldl[didx-1].fdtyp))); curfieldn=didx; // Return without errors return(0); } static int tabdatafunc(string dstr,int dint,double ddbl, int dval,int dtype,string dtable,string dfield,int didx) /* // Data callback function // Return value : // zero if done or (-1) on data error // Parameters : // string dstr : String/Date data // int dint : Integer/Boolean data // double ddbl : Float data // int dval : Data valid flag // int dtype : Data type // string dtable : Data table name // string dfield : Data field name // int didx : Data output field index */ { // Messages string ERRNIMPL = M("IMPLEMENTIERUNGSLUECKE IN %s !", "IMPLEMENTATION GAP IN %s !") + M(" (BITTE AN PROGRAMMIERER MELDEN!)", " (PLEASE REPORT TO PROGRAMMER!)"); string str; // Entry string buffer // Store the current entry switch (dtype) { // Integer case SQLINT : sprintf(str,"%d",dint); break; // Double case SQLDBL : sprintf(str,"%10.8E",ddbl); break; // String case SQLSTR : sprintf(str,"'%s'",dstr); break; // Date case SQLDATE : sprintf(str,"%s",dstr); break; // Boolean case SQLBOOL : str=dint ? "TRUE" : "FALSE"; break; // Unknown/illegal (implementation gap!) default : errormsg(ERRNIMPL,"sql.ulh"); break; } // Update the maximum field entry length #ifdef OPTIMIZE if (strlen(str)>curfieldl[didx-1].ml) curfieldl[didx-1].ml=strlen(str); #else curfieldl[didx-1].ml=maxint(curfieldl[didx-1].ml,strlen(str)); #endif // Store the entry string to the entry table curtabentry[didx-1]=str; if (didx==curfieldn) curetab[curen++]=curtabentry; // Return without errors return(0); } //__________________________________________________________________ // End library-specific source code #endif // LIBSQL #endif // USELIB // Conditional file inclusion end #endif // INCLUDE_SQL // User Language include file end