2018-07-20 Fred Gleason <fredg@paravelsystems.com>

* Added an 'IMPORTER_LINES' table to the database.
	* Incremented the database version to 295.
	* Refactored the log importer code to use the static 'IMPORTER_LINES'
	table.
This commit is contained in:
Fred Gleason 2018-07-20 19:24:11 -04:00
parent 0dc7a4e698
commit c52c9b9f8a
17 changed files with 197 additions and 106 deletions

View File

@ -17201,3 +17201,8 @@
* Removed the Auxiliary Fields from the podcasting system.
* Fixed a regression in the RDFeed system that caused segfaults
when accessing channel XML.
2018-07-20 Fred Gleason <fredg@paravelsystems.com>
* Added an 'IMPORTER_LINES' table to the database.
* Incremented the database version to 295.
* Refactored the log importer code to use the static 'IMPORTER_LINES'
table.

View File

@ -50,6 +50,7 @@ EXTRA_DIST = audio_cards.txt\
gpis.txt\
gpos.txt\
groups.txt\
importer_lines.txt\
isci_xreference.txt\
jack_clients.txt\
livewire_gpio_slots.txt\

View File

@ -0,0 +1,27 @@
IMPORTER_LINES Layout for Rivendell
The IMPORTER_LINES table holds ephemeral data use for log
importation.
FIELD NAME TYPE REMARKS
----------------------------------------------------------------
ID int(10) unsigned Primary key, auto increment
STATION_NAME char(64) From STATIONS.NAME
PROCESS_ID int unsigned
LINE_ID int(10) unsigned
START_HOUR int (11) signed
START_SECS int(11) signed
CART_NUMBER int (10) unsigned
TITLE char(255)
LENGTH int (11) signed
INSERT_BREAK enum('N','Y')
INSERT_TRACK enum('N','Y')
INSERT_FIRST int (10) unsigned
TRACK_STRING char(255)
EXT_DATA char(32)
EXT_EVENT_ID char(32)
EXT_ANNC_TYPE char(8)
EXT_CART_NAME char(32)
LINK_START_TIME time
LINK_LENGTH int (11) signed
EVENT_USED enum('N','Y')

View File

@ -24,7 +24,7 @@
/*
* Current Database Version
*/
#define RD_VERSION_DATABASE 294
#define RD_VERSION_DATABASE 295
#endif // DBVERSION_H

View File

@ -25,8 +25,9 @@
//
// Global Classes
//
RDClock::RDClock()
RDClock::RDClock(RDStation *station)
{
clock_station=station;
clear();
}
@ -162,7 +163,7 @@ bool RDClock::load()
"order by START_TIME";
q=new RDSqlQuery(sql);
while(q->next()) {
clock_events.push_back(RDEventLine());
clock_events.push_back(RDEventLine(clock_station));
clock_events.back().setName(q->value(0).toString());
clock_events.back().setStartTime(QTime().addMSecs(q->value(1).toInt()));
clock_events.back().setLength(q->value(2).toInt());
@ -235,11 +236,11 @@ bool RDClock::insert(const QString &event_name,int line)
}
delete q;
if(line>=size()) {
clock_events.push_back(RDEventLine());
clock_events.push_back(RDEventLine(clock_station));
}
else {
std::vector<RDEventLine>::iterator it=clock_events.begin()+line;
clock_events.insert(it,1,RDEventLine());
clock_events.insert(it,1,RDEventLine(clock_station));
}
clock_events[line].setName(event_name);
clock_events[line].load();
@ -307,7 +308,7 @@ bool RDClock::generateLog(int hour,const QString &logname,
{
QString sql;
RDSqlQuery *q;
RDEventLine eventline;
RDEventLine eventline(clock_station);
sql=QString("select ")+
"EVENT_NAME,"+ // 00

View File

@ -23,14 +23,13 @@
#include <vector>
#include <qsqldatabase.h>
#include <rdevent_line.h>
#include <rdstation.h>
class RDClock
{
public:
RDClock();
RDClock(RDStation *station);
QString name() const;
void setName(const QString &name);
QString shortName() const;
@ -64,6 +63,7 @@ class RDClock
std::vector<RDEventLine> clock_events;
unsigned artistsep;
bool rules_modified;
RDStation *clock_station;
};
#endif // RDCLOCK_H

View File

@ -29,8 +29,9 @@
#include "rdeventimportlist.h"
#include "schedcartlist.h"
RDEventLine::RDEventLine()
RDEventLine::RDEventLine(RDStation *station)
{
event_station=station;
event_preimport_list=new RDEventImportList();
event_postimport_list=new RDEventImportList();
clear();
@ -908,7 +909,7 @@ bool RDEventLine::generateLog(QString logname,const QString &svcname,
bool RDEventLine::linkLog(RDLogEvent *e,const QString &svcname,
RDLogLine *link_logline,const QString &track_str,
const QString &label_cart,const QString &track_cart,
const QString &import_table,QString *errors)
QString *errors)
{
QString sql;
RDSqlQuery *q;
@ -993,11 +994,13 @@ bool RDEventLine::linkLog(RDLogEvent *e,const QString &svcname,
"TRACK_STRING,"+ // 11
"LINK_START_TIME,"+ // 12
"LINK_LENGTH "+ // 13
"from `"+import_table+"` where "+
"from IMPORTER_LINES where "+
"STATION_NAME=\""+RDEscapeString(event_station->name())+"\" && "+
QString().sprintf("PROCESS_ID=%u && ",getpid())+
QString().sprintf("(START_HOUR=%d)&&",start_start_hour)+
QString().sprintf("(START_SECS>=%d)&&",start_start_secs/1000)+
QString().sprintf("(START_SECS<=%d)&&",end_start_secs/1000)+
"(EVENT_USED=\"N\") order by ID";
"(EVENT_USED=\"N\") order by LINE_ID";
q=new RDSqlQuery(sql);
while(q->next()) {
int length=GetLength(q->value(0).toUInt(),q->value(2).toInt());
@ -1148,8 +1151,10 @@ bool RDEventLine::linkLog(RDLogEvent *e,const QString &svcname,
//
// Mark Events as Used
//
sql=QString("update `")+import_table+"` set "+
sql=QString("update IMPORTER_LINES set ")+
"EVENT_USED=\"Y\" where "+
"STATION_NAME=\""+RDEscapeString(event_station->name())+"\" && "+
QString().sprintf("PROCESS_ID=%u && ",getpid())+
QString().sprintf("(START_HOUR=%d)&&",start_start_hour)+
QString().sprintf("(START_SECS>=%d)&&",start_start_secs/1000)+
QString().sprintf("(START_SECS<=%d)&&",end_start_secs/1000)+
@ -1164,8 +1169,11 @@ bool RDEventLine::linkLog(RDLogEvent *e,const QString &svcname,
addMSecs(link_logline->linkLength());
if(event_use_autofill&&(event_start_time<=time)) {
QTime fill_start_time=time;
sql=QString("select AUTOFILLS.CART_NUMBER,CART.FORCED_LENGTH from ")+
"AUTOFILLS left join CART on AUTOFILLS.CART_NUMBER=CART.NUMBER where "+
sql=QString("select ")+
"AUTOFILLS.CART_NUMBER,"+ // 00
"CART.FORCED_LENGTH "+ // 01
"from AUTOFILLS left join CART "+
"on AUTOFILLS.CART_NUMBER=CART.NUMBER where "+
"(AUTOFILLS.SERVICE=\""+RDEscapeString(svcname)+"\")&&"+
QString().sprintf("(CART.FORCED_LENGTH<=%d)&&",time.msecsTo(end_time))+
"(CART.FORCED_LENGTH>0) "+

View File

@ -21,19 +21,19 @@
#ifndef RDEVENT_LINE_H
#define RDEVENT_LINE_H
#include <qsqldatabase.h>
#include <qdatetime.h>
#include <rdlog_event.h>
#include <rdeventimportlist.h>
#include <rdlog_line.h>
#include <rdstation.h>
class RDEventLine
{
public:
enum ImportSource {None=0,Traffic=1,Music=2,Scheduler=3};
enum InsertFirst {InsertNone=0,InsertBreak=1,InsertTrack=2};
RDEventLine();
RDEventLine(RDStation *station);
QString name() const;
void setName(const QString &name);
QString properties() const;
@ -84,7 +84,7 @@ class RDEventLine
bool linkLog(RDLogEvent *e,const QString &svcname,
RDLogLine *link_logline,const QString &track_str,
const QString &label_cart,const QString &track_cart,
const QString &import_table,QString *errors);
QString *errors);
private:
int GetLength(unsigned cartnum,int def_length=0);
@ -112,6 +112,7 @@ class RDEventLine
QString event_have_code;
QString event_have_code2;
unsigned event_title_sep;
RDStation *event_station;
};
#endif
#endif // RDEVENT_LINE_H

View File

@ -20,12 +20,13 @@
#include <rdgrid.h>
RDGrid::RDGrid(QString svc_name)
RDGrid::RDGrid(QString svc_name,RDStation *station)
{
grid_name=svc_name;
grid_station=station;
for(int i=0;i<7;i++) {
for(int j=0;j<24;j++) {
grid_clocks[i][j]=new RDClock();
grid_clocks[i][j]=new RDClock(grid_station);
}
}
}

View File

@ -24,11 +24,12 @@
#include <qsqldatabase.h>
#include <rdclock.h>
#include <rdstation.h>
class RDGrid
{
public:
RDGrid(QString svc_name);
RDGrid(QString svc_name,RDStation *station);
QString serviceName() const;
void setServiceName(QString name);
RDClock *clock(int dayofweek,int hour);
@ -40,6 +41,7 @@ class RDGrid
private:
QString grid_name;
RDClock *grid_clocks[7][24];
RDStation *grid_station;
};

View File

@ -356,7 +356,7 @@ QString RDSvc::importFilename(ImportSource src,const QDate &date) const
bool RDSvc::import(ImportSource src,const QDate &date,const QString &break_str,
const QString &track_str,const QString &dest_table) const
const QString &track_str) const
{
FILE *infile;
QString src_str;
@ -383,13 +383,13 @@ bool RDSvc::import(ImportSource src,const QDate &date,const QString &break_str,
// Set Import Source
//
switch(src) {
case RDSvc::Traffic:
src_str="TFC";
break;
case RDSvc::Traffic:
src_str="TFC";
break;
case RDSvc::Music:
src_str="MUS";
break;
case RDSvc::Music:
src_str="MUS";
break;
}
//
@ -505,30 +505,10 @@ bool RDSvc::import(ImportSource src,const QDate &date,const QString &break_str,
//
// Setup Data Source and Destination
//
rda->dropTable(dest_table);
sql=QString("create table ")+
"`"+dest_table+"` ("+
"ID int primary key,"+
"START_HOUR int not null,"+
"START_SECS int not null,"+
"CART_NUMBER int unsigned,"+
"TITLE char(255),"+
"LENGTH int,"+
"INSERT_BREAK enum('N','Y') default 'N',"+
"INSERT_TRACK enum('N','Y') default 'N',"+
"INSERT_FIRST int unsigned default 0,"+
"TRACK_STRING char(255),"+
"EXT_DATA char(32),"+
"EXT_EVENT_ID char(32),"+
"EXT_ANNC_TYPE char(8),"+
"EXT_CART_NAME char(32),"+
"LINK_START_TIME time default NULL,"+
"LINK_LENGTH int default NULL,"+
"EVENT_USED enum('N','Y') default 'N',"+
"INDEX START_TIME_IDX (START_HOUR,START_SECS)) "+
svc_config->createTablePostfix();
q=new RDSqlQuery(sql);
delete q;
sql=QString("delete from IMPORTER_LINES where ")+
"STATION_NAME=\""+RDEscapeString(svc_station->name())+"\" && "+
QString().sprintf("PROCESS_ID=%u",getpid());
RDSqlQuery::apply(sql);
//
// Parse and Save
@ -601,9 +581,10 @@ bool RDSvc::import(ImportSource src,const QDate &date,const QString &break_str,
if(start_time_ok&&(cart_ok||
((!label_cart.isEmpty())&&(cartname==label_cart))||
((!track_cart.isEmpty())&&(cartname==track_cart)))) {
sql=QString("insert into ")+
"`"+dest_table+"` set "+
QString().sprintf("ID=%d,",line_id++)+
sql=QString("insert into IMPORTER_LINES set ")+
"STATION_NAME=\""+RDEscapeString(svc_station->name())+"\","+
QString().sprintf("PROCESS_ID=%d,",getpid())+
QString().sprintf("LINE_ID=%d,",line_id++)+
QString().sprintf("START_HOUR=%d,",start_hour)+
QString().sprintf("START_SECS=%d,",
60*start_minutes+start_seconds)+
@ -620,7 +601,7 @@ bool RDSvc::import(ImportSource src,const QDate &date,const QString &break_str,
// Insert Break
//
if(insert_break) {
sql=QString("update ")+"`"+dest_table+"` set "+
sql=QString("update IMPORTER_LINES set ")+
"INSERT_BREAK=\"Y\"";
if(break_first) {
sql+=QString().sprintf(",INSERT_FIRST=%d",
@ -632,7 +613,10 @@ bool RDSvc::import(ImportSource src,const QDate &date,const QString &break_str,
QString().sprintf(",LINK_LENGTH=%d",
link_length);
}
sql+=QString().sprintf(" where ID=%d",line_id-1);
sql+=QString(" where ")+
"STATION_NAME=\""+RDEscapeString(svc_station->name())+"\" && "+
QString().sprintf("PROCESS_ID=%u && ",getpid())+
QString().sprintf("LINE_ID=%d",line_id-1);
q=new RDSqlQuery(sql);
delete q;
}
@ -641,19 +625,23 @@ bool RDSvc::import(ImportSource src,const QDate &date,const QString &break_str,
//
if(insert_track) {
if(track_first) {
sql=QString("update ")+
"`"+dest_table+"` set "+
sql=QString("update IMPORTER_LINES set ")+
"INSERT_TRACK=\"Y\","+
"TRACK_STRING=\""+RDEscapeString(track_label)+"\","+
QString().sprintf("INSERT_FIRST=%d ",RDEventLine::InsertTrack)+
QString().sprintf("where ID=%d",line_id-1);
QString("where ")+
"STATION_NAME=\""+RDEscapeString(svc_station->name())+"\" && "+
QString().sprintf("PROCESS_ID=%u && ",getpid())+
QString().sprintf("LINE_ID=%d",line_id-1);
}
else {
sql=QString("update ")+
"`"+dest_table+"` set "+
sql=QString("update IMPORTER_LINES set ")+
"INSERT_TRACK=\"Y\","+
"TRACK_STRING=\""+RDEscapeString(track_label)+"\" "+
QString().sprintf("where ID=%d",line_id-1);
QString("where ")+
"STATION_NAME=\""+RDEscapeString(svc_station->name())+"\" && "+
QString().sprintf("PROCESS_ID=%u && ",getpid())+
QString().sprintf("LINE_ID=%d",line_id-1);
}
q=new RDSqlQuery(sql);
delete q;
@ -714,8 +702,7 @@ bool RDSvc::generateLog(const QDate &date,const QString &logname,
{
QString sql;
RDSqlQuery *q;
RDClock clock;
// QString err_msg;
RDClock clock(svc_station);
RDLog *log=NULL;
RDLogLock *log_lock=NULL;
@ -843,10 +830,7 @@ bool RDSvc::linkLog(RDSvc::ImportSource src,const QDate &date,
//
// Import File
//
QString import_name=QString("IMPORT_")+svc_name+"_"+date.toString("yyyyMMdd");
import_name.replace(" ","_");
if(!import(src,date,breakString(),trackString(src),import_name)) {
if(!import(src,date,breakString(),trackString(src))) {
*err_msg=tr("Import failed");
delete log_lock;
return false;
@ -858,15 +842,15 @@ bool RDSvc::linkLog(RDSvc::ImportSource src,const QDate &date,
RDLogLine::Type src_type=RDLogLine::UnknownType;
RDLog::Source link_src=RDLog::SourceMusic;
switch(src) {
case RDSvc::Music:
src_type=RDLogLine::MusicLink;
link_src=RDLog::SourceMusic;
break;
case RDSvc::Music:
src_type=RDLogLine::MusicLink;
link_src=RDLog::SourceMusic;
break;
case RDSvc::Traffic:
src_type=RDLogLine::TrafficLink;
link_src=RDLog::SourceTraffic;
break;
case RDSvc::Traffic:
src_type=RDLogLine::TrafficLink;
link_src=RDLog::SourceTraffic;
break;
}
RDLog *log=new RDLog(logname);
int current_link=0;
@ -882,11 +866,11 @@ bool RDSvc::linkLog(RDSvc::ImportSource src,const QDate &date,
for(int i=0;i<src_event->size();i++) {
logline=src_event->logLine(i);
if(logline->type()==src_type) {
RDEventLine *e=new RDEventLine();
RDEventLine *e=new RDEventLine(svc_station);
e->setName(logline->linkEventName());
e->load();
e->linkLog(dest_event,svc_name,logline,track_str,label_cart,track_cart,
import_name,&autofill_errors);
&autofill_errors);
delete e;
emit generationProgress(1+(24*current_link++)/total_links);
}
@ -919,13 +903,17 @@ bool RDSvc::linkLog(RDSvc::ImportSource src,const QDate &date,
dest_event->validate(&missing_report,date);
bool event=false;
QString link_report=tr("The following events were not placed:\n");
sql=QString().sprintf("select `%s`.START_HOUR,`%s`.START_SECS,\
`%s`.CART_NUMBER,CART.TITLE from `%s` LEFT JOIN CART\
ON `%s`.CART_NUMBER=CART.NUMBER \
where `%s`.EVENT_USED=\"N\"",
(const char *)import_name,(const char *)import_name,
(const char *)import_name,(const char *)import_name,
(const char *)import_name,(const char *)import_name);
sql=QString("select ")+
"IMPORTER_LINES.START_HOUR,"+ // 00
"IMPORTER_LINES.START_SECS,"+ // 01
"IMPORTER_LINES.CART_NUMBER,"+ // 02
"CART.TITLE "+ // 03
"from IMPORTER_LINES left join CART "+
"on IMPORTER_LINES.CART_NUMBER=CART.NUMBER where "+
"IMPORTER_LINES.STATION_NAME=\""+
RDEscapeString(svc_station->name())+"\" && "+
QString().sprintf("IMPORTER_LINES.PROCESS_ID=%u && ",getpid())+
"IMPORTER_LINES.EVENT_USED=\"N\"";
q=new RDSqlQuery(sql);
while(q->next()) {
event=true;
@ -963,8 +951,11 @@ bool RDSvc::linkLog(RDSvc::ImportSource src,const QDate &date,
delete src_event;
delete dest_event;
// printf("Import Table: %s\n",(const char *)import_name);
rda->dropTable(import_name);
sql=QString("delete from IMPORTER_LINES where ")+
"STATION_NAME=\""+RDEscapeString(svc_station->name())+"\" && "+
QString().sprintf("PROCESS_ID=%u",getpid());
// printf("Importer Table Cleanup SQL: %s\n",(const char *)sql);
RDSqlQuery::apply(sql);
delete log_lock;
return true;

View File

@ -87,8 +87,7 @@ class RDSvc : public QObject
void setImportLength(ImportSource src,ImportField field,int len) const;
QString importFilename(ImportSource src,const QDate &date) const;
bool import(ImportSource src,const QDate &date,const QString &break_str,
const QString &track_str,const QString &dest_table)
const;
const QString &track_str) const;
bool generateLog(const QDate &date,const QString &logname,
const QString &nextname,QString *report,RDUser *user,
QString *err_msg);

View File

@ -27,6 +27,7 @@
#include <rddatedecode.h>
#include <rddatedialog.h>
#include <rddb.h>
#include <rdescape_string.h>
#include <rdevent_line.h>
#include <rdlistviewitem.h>
#include <rdpasswd.h>
@ -180,18 +181,27 @@ void TestImport::importData()
test_events_list->clear();
if(!test_svc->import(test_src,test_date_edit->date(),test_svc->breakString(),
test_svc->trackString(test_src),QString().
sprintf("%s_TEST_IMP",
(const char *)test_svc->name()))) {
test_svc->trackString(test_src))) {
QMessageBox::information(this,tr("Import Error"),
tr("There was an error during import\nplease check your settings and try again."));
return;
}
QString sql=QString().sprintf("select START_HOUR,START_SECS,EXT_CART_NAME,\
LENGTH,EXT_DATA,EXT_EVENT_ID,EXT_ANNC_TYPE,\
INSERT_BREAK,INSERT_TRACK,INSERT_FIRST,TITLE,\
TRACK_STRING from `%s_TEST_IMP`",
(const char *)test_svc->name());
QString sql=QString("select ")+
"START_HOUR,"+ // 00
"START_SECS,"+ // 01
"EXT_CART_NAME,"+ // 02
"LENGTH,"+ // 03
"EXT_DATA,"+ // 04
"EXT_EVENT_ID,"+ // 05
"EXT_ANNC_TYPE,"+ // 06
"INSERT_BREAK,"+ // 07
"INSERT_TRACK,"+ // 08
"INSERT_FIRST,"+ // 09
"TITLE,"+ // 10
"TRACK_STRING "+ // 11
"from IMPORTER_LINES where "+
"STATION_NAME=\""+RDEscapeString(rda->station()->name())+"\" && "+
QString().sprintf("PROCESS_ID=%u",getpid());
RDSqlQuery *q=new RDSqlQuery(sql);
while(q->next()) {
if(q->value(9).toUInt()==RDEventLine::InsertBreak) {
@ -242,8 +252,12 @@ void TestImport::importData()
item->setText(6,q->value(6).toString());
}
delete q;
// printf("IMPORT TABLE: %s_TEST_IMP\n",(const char *)test_svc->name());
rda->dropTable(test_svc->name()+"_TEST_IMP");
sql=QString("delete from IMPORTER_LINES where ")+
"STATION_NAME=\""+RDEscapeString(rda->station()->name())+"\" && "+
QString().sprintf("PROCESS_ID=%u",getpid());
// printf("IMPORTER_LINES cleanup SQL: %s\n",(const char *)sql);
RDSqlQuery::apply(sql);
}

View File

@ -239,7 +239,7 @@ EditClock::EditClock(QString clockname,bool new_clock,
// Populate Data
//
sched_rules_list = new SchedRulesList(clockname,rda->config());
edit_clock=new RDClock();
edit_clock=new RDClock(rda->station());
edit_clock->setName(clockname);
edit_clock->load();
edit_shortname_edit->setText(edit_clock->shortName());
@ -283,7 +283,7 @@ void EditClock::selectionChangedData(QListViewItem *l)
void EditClock::addData()
{
int line=0;
RDEventLine eventline;
RDEventLine eventline(rda->station());
RDListViewItem *item=(RDListViewItem *)edit_clocks_list->selectedItem();
if(item!=NULL) {
@ -344,7 +344,7 @@ void EditClock::cloneData()
RDEventLine *selectedEventLine = edit_clock->eventLine(line);
RDEventLine eventline;
RDEventLine eventline(rda->station());
eventline.setName(selectedEventLine->name());
eventline.setStartTime(selectedEventLine->startTime().addMSecs(selectedEventLine->length()));
eventline.setLength(selectedEventLine->length());

View File

@ -38,6 +38,17 @@ bool MainObject::RevertSchema(int cur_schema,int set_schema,QString *err_msg) co
//
//
// Revert 295
//
if((cur_schema==295)&&(set_schema<cur_schema)) {
if(!DropTable("IMPORTER_LINES",err_msg)) {
return false;
}
WriteSchemaVersion(--cur_schema);
}
//
// Revert 294
//

View File

@ -132,7 +132,7 @@ void MainObject::InitializeSchemaMap() {
global_version_map["2.17"]=268;
global_version_map["2.18"]=272;
global_version_map["2.19"]=275;
global_version_map["2.20"]=294;
global_version_map["2.20"]=295;
}

View File

@ -7840,7 +7840,37 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg) co
}
delete q;
WriteSchemaVersion(++cur_schema);
}
if((cur_schema<295)&&(set_schema>cur_schema)) {
sql=QString("create table IMPORTER_LINES (")+
"ID int not null primary key auto_increment,"+
"STATION_NAME char(64) not null,"+
"PROCESS_ID int unsigned not null,"
"LINE_ID int unsigned not null,"+
"START_HOUR int not null,"+
"START_SECS int not null,"+
"CART_NUMBER int unsigned,"+
"TITLE char(255),"+
"LENGTH int,"+
"INSERT_BREAK enum('N','Y') default 'N',"+
"INSERT_TRACK enum('N','Y') default 'N',"+
"INSERT_FIRST int unsigned default 0,"+
"TRACK_STRING char(255),"+
"EXT_DATA char(32),"+
"EXT_EVENT_ID char(32),"+
"EXT_ANNC_TYPE char(8),"+
"EXT_CART_NAME char(32),"+
"LINK_START_TIME time default NULL,"+
"LINK_LENGTH int default NULL,"+
"EVENT_USED enum('N','Y') default 'N',"+
"index STATION_NAME_PROCESS_ID_IDX (STATION_NAME,PROCESS_ID),"+
"unique index START_TIME_IDX (STATION_NAME,PROCESS_ID,START_HOUR,START_SECS,LINE_ID)) "+
db_table_create_postfix;
if(!RDSqlQuery::apply(sql,err_msg)) {
return false;
}
WriteSchemaVersion(++cur_schema);
}