*============================================================================== * Function: NEXTID * Purpose: Get the next available value for the specified field * Author: Doug Hennig * Copyright: (c) 1995 Stonefield Systems Group Inc. * Last Revision: 04/29/99 * Parameters: tcAlias - the alias of the table of interest (optional: * if it wasn't specified, the current table is used) * tcField - the name of the field to assign (optional: if * it wasn't specified, the primary key is used) * Returns: the next available key value (either numeric or left- * justified string, depending on the field type), or a * null string if there was a problem * Environment in: the table of interest is open * the NEXTID table is either open or is available to be * opened * Environment out: if NEXTID was open, it is positioned to the appropriate * record for the field and table * if there was no record for the field and table in NEXTID, * one is created with a starting value of 1 * the KEY field of the appropriate record in NEXTID is * incremented *============================================================================== lparameters tcAlias, ; tcField local lcCurrTalk, ; lcCurrTalkWindow, ; lcAlias, ; luReturn ,; lcDatabase, ; lcField, ; lcCurrDBC, ; lcTable, ; lcTag, ; llUsed, ; lnCurrReprocess, ; liKey, ; lcMax, ; laID[1] * Save the setting of TALK and turn it off. if set('TALK') = 'ON' set talk off lcCurrTalk = 'ON' lcCurrTalkWindow = set('TALK', 1) else lcCurrTalk = 'OFF' endif set('TALK') = 'ON' * If the alias wasn't passed, use the currently selected table. Give an * error and return if there is no table. lcAlias = iif(vartype(tcAlias) <> 'C' or empty(tcAlias), alias(), ; upper(tcAlias)) assert not empty(lcAlias) ; message 'NEXTID: no table selected' * Initialize the return value and get the database for the table. luReturn = 0 luReturn = .NULL. lcDatabase = iif(used(lcAlias), cursorgetprop('Database', lcAlias), '') do case * If the field was passed, use it. case vartype(tcField) = 'C' and not empty(tcField) lcField = upper(tcField) * If the field wasn't passed and the table isn't in a database, we won't have * a field. case empty(lcDatabase) lcField = '' * If the field wasn't passed and we have a database, find the primary key for * the table. If we can't or if it's a compound key, we won't have a field. otherwise lcCurrDBC = dbc() lcCurrDBC = iif(empty(lcCurrDBC), '', '"' + lcCurrDBC + '"') set database to (lcDatabase) lcTable = cursorgetprop('SourceName', lcAlias) lcTag = dbgetprop(lcTable, 'Table', 'PrimaryKey') set database to &lcCurrDBC if empty(lcTag) lcField = '' else lcField = key(tagno(lcTag, '', lcAlias), lcAlias) if ',' $ lcField or '+' $ lcField lcField = '' endif ',' $ lcField ... endif empty(lcTag) endcase * Open the NEXTID table (if necessary). llUsed = used('NEXTID') if not llUsed use NEXTID again shared in 0 endif not llUsed * Try to find a record for the field. If there isn't one, create it. lnCurrReprocess = set('REPROCESS') set reprocess to 10 seconds if not seek(padr(lcAlias, len(NEXTID.TABLE)) + ; padr(lcField, len(NEXTID.FIELD)), 'NEXTID', 'NEXTID') if empty(lcField) or type(lcAlias + '.' + lcField) = 'U' liKey = 0 else lcMax = iif(type(lcAlias + '.' + lcField) = 'C', ; 'val(' + lcField + ')', lcField) select max(&lcMax) from (lcAlias) into array laID liKey = iif(_tally > 0, laID[1], 0) endif empty(lcField) ... insert into NEXTID (TABLE, FIELD, KEY) values (lcAlias, lcField, liKey) endif not seek(padr(lcAlias, ... * If we can lock the record, increment the KEY value (rolling over to 1 if * necessary) and assign it to luReturn. if rlock('NEXTID') liKey = iif(NEXTID.KEY >= 2^32/2 - 1, 1, NEXTID.KEY + 1) replace KEY with liKey in NEXTID luReturn = iif(type(lcAlias + '.' + lcField) = 'C', ltrim(str(liKey)), ; liKey) unlock in NEXTID endif rlock('NEXTID') * Cleanup and return. if not llUsed use in NEXTID endif not llUsed set reprocess to lnCurrReprocess if lcCurrTalk = 'ON' set talk &lcCurrTalkWindow set talk on endif lcCurrTalk = 'ON' return luReturn