tables unified, normal tests passing

This commit is contained in:
Radu Ioan Fericean
2015-11-04 17:20:19 +02:00
parent 4b5ff94fd2
commit 21ac196222
11 changed files with 224 additions and 994 deletions

View File

@@ -121,10 +121,8 @@ func TestCsvLclEmptyTables(t *testing.T) {
return // No point in going further
}
}
for _, tbl := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA} {
if _, err := mysql.Db.Query(fmt.Sprintf("SELECT 1 from %s", tbl)); err != nil {
t.Fatal(err.Error())
}
if _, err := mysql.Db.Query(fmt.Sprintf("SELECT 1 from %s", utils.TBL_CDRS)); err != nil {
t.Fatal(err.Error())
}
}

View File

@@ -1,13 +1,14 @@
--
-- Table structure for table `cdrs_primary`
-- Table structure for table `cdrs`
--
DROP TABLE IF EXISTS cdrs_primary;
DROP TABLE IF EXISTS cdrs;
CREATE TABLE cdrs_primary (
id int(11) NOT NULL AUTO_INCREMENT,
cgrid char(40) NOT NULL,
tor varchar(16) NOT NULL,
runid varchar(64) NOT NULL,
tor varchar(16) NOT NULL,
accid varchar(64) NOT NULL,
cdrhost varchar(64) NOT NULL,
cdrsource varchar(64) NOT NULL,
@@ -24,85 +25,16 @@ CREATE TABLE cdrs_primary (
`usage` DECIMAL(30,9) NOT NULL,
supplier varchar(128) NOT NULL,
disconnect_cause varchar(64) NOT NULL,
extra_fields text NOT NULL,
cost DECIMAL(20,4) NOT NULL,
timespans text,
cost_source varchar(64) NOT NULL,
extra_info text,
created_at TIMESTAMP,
updated_at TIMESTAMP,
deleted_at TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY cgrid (cgrid),
KEY answer_time_idx (answer_time),
KEY deleted_at_idx (deleted_at)
);
--
-- Table structure for table `cdrs_extra`
--
DROP TABLE IF EXISTS cdrs_extra;
CREATE TABLE cdrs_extra (
id int(11) NOT NULL AUTO_INCREMENT,
cgrid char(40) NOT NULL,
extra_fields text NOT NULL,
created_at TIMESTAMP,
deleted_at TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY cgrid (cgrid),
KEY deleted_at_idx (deleted_at)
);
--
-- Table structure for table `cost_details`
--
DROP TABLE IF EXISTS cost_details;
CREATE TABLE cost_details (
id int(11) NOT NULL AUTO_INCREMENT,
cgrid char(40) NOT NULL,
runid varchar(64) NOT NULL,
tor varchar(16) NOT NULL,
direction varchar(8) NOT NULL,
tenant varchar(128) NOT NULL,
category varchar(32) NOT NULL,
account varchar(128) NOT NULL,
subject varchar(128) NOT NULL,
destination varchar(128) NOT NULL,
cost DECIMAL(20,4) NOT NULL,
timespans text,
cost_source varchar(64) NOT NULL,
created_at TIMESTAMP,
updated_at TIMESTAMP,
deleted_at TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `costid` (`cgrid`,`runid`),
KEY deleted_at_idx (deleted_at)
);
--
-- Table structure for table `rated_cdrs`
--
DROP TABLE IF EXISTS rated_cdrs;
CREATE TABLE `rated_cdrs` (
id int(11) NOT NULL AUTO_INCREMENT,
cgrid char(40) NOT NULL,
runid varchar(64) NOT NULL,
reqtype varchar(24) NOT NULL,
direction varchar(8) NOT NULL,
tenant varchar(64) NOT NULL,
category varchar(32) NOT NULL,
account varchar(128) NOT NULL,
subject varchar(128) NOT NULL,
destination varchar(128) NOT NULL,
setup_time datetime NOT NULL,
pdd DECIMAL(12,9) NOT NULL,
answer_time datetime NOT NULL,
`usage` DECIMAL(30,9) NOT NULL,
supplier varchar(128) NOT NULL,
disconnect_cause varchar(64) NOT NULL,
cost DECIMAL(20,4) DEFAULT NULL,
extra_info text,
created_at TIMESTAMP,
updated_at TIMESTAMP,
deleted_at TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `costid` (`cgrid`,`runid`),
KEY deleted_at_idx (deleted_at)
);

View File

@@ -1,103 +1,36 @@
--
-- Table structure for table `cdrs_primary`
-- Table structure for table `cdrs`
--
DROP TABLE IF EXISTS cdrs_primary;
CREATE TABLE cdrs_primary (
id SERIAL PRIMARY KEY,
cgrid CHAR(40) NOT NULL,
tor VARCHAR(16) NOT NULL,
accid VARCHAR(64) NOT NULL,
cdrhost VARCHAR(64) NOT NULL,
cdrsource VARCHAR(64) NOT NULL,
reqtype VARCHAR(24) NOT NULL,
direction VARCHAR(8) NOT NULL,
tenant VARCHAR(64) NOT NULL,
category VARCHAR(32) NOT NULL,
account VARCHAR(128) NOT NULL,
subject VARCHAR(128) NOT NULL,
destination VARCHAR(128) NOT NULL,
setup_time TIMESTAMP NOT NULL,
pdd NUMERIC(12,9) NOT NULL,
answer_time TIMESTAMP NOT NULL,
usage NUMERIC(30,9) NOT NULL,
supplier VARCHAR(128) NOT NULL,
disconnect_cause VARCHAR(64) NOT NULL,
created_at TIMESTAMP,
deleted_at TIMESTAMP,
UNIQUE (cgrid)
DROP TABLE IF EXISTS cdrs;
CREATE TABLE cdrs (
id SERIAL PRIMARY KEY,
cgrid CHAR(40) NOT NULL,
runid VARCHAR(64) NOT NULL,
tor VARCHAR(16) NOT NULL,
accid VARCHAR(64) NOT NULL,
cdrhost VARCHAR(64) NOT NULL,
cdrsource VARCHAR(64) NOT NULL,
reqtype VARCHAR(24) NOT NULL,
direction VARCHAR(8) NOT NULL,
tenant VARCHAR(64) NOT NULL,
category VARCHAR(32) NOT NULL,
account VARCHAR(128) NOT NULL,
subject VARCHAR(128) NOT NULL,
destination VARCHAR(128) NOT NULL,
setup_time TIMESTAMP NOT NULL,
pdd NUMERIC(12,9) NOT NULL,
answer_time TIMESTAMP NOT NULL,
usage NUMERIC(30,9) NOT NULL,
supplier VARCHAR(128) NOT NULL,
disconnect_cause VARCHAR(64) NOT NULL,
extra_fields jsonb NOT NULL,
cost NUMERIC(20,4) DEFAULT NULL,
timespans jsonb,
cost_source VARCHAR(64) NOT NULL,
extra_info text,
created_at TIMESTAMP,
updated_at TIMESTAMP,
deleted_at TIMESTAMP,
UNIQUE (cgrid)
);
CREATE INDEX answer_time_idx ON cdrs_primary (answer_time);
CREATE INDEX deleted_at_cp_idx ON cdrs_primary (deleted_at);
--
-- Table structure for table `cdrs_extra`
--
DROP TABLE IF EXISTS cdrs_extra;
CREATE TABLE cdrs_extra (
id SERIAL PRIMARY KEY,
cgrid CHAR(40) NOT NULL,
extra_fields jsonb NOT NULL,
created_at TIMESTAMP,
deleted_at TIMESTAMP,
UNIQUE (cgrid)
);
CREATE INDEX deleted_at_ce_idx ON cdrs_extra (deleted_at);
--
-- Table structure for table `cost_details`
--
DROP TABLE IF EXISTS cost_details;
CREATE TABLE cost_details (
id SERIAL PRIMARY KEY,
cgrid CHAR(40) NOT NULL,
runid VARCHAR(64) NOT NULL,
tor VARCHAR(16) NOT NULL,
direction VARCHAR(8) NOT NULL,
tenant VARCHAR(128) NOT NULL,
category VARCHAR(32) NOT NULL,
account VARCHAR(128) NOT NULL,
subject VARCHAR(128) NOT NULL,
destination VARCHAR(128) NOT NULL,
cost NUMERIC(20,4) NOT NULL,
timespans jsonb,
cost_source VARCHAR(64) NOT NULL,
created_at TIMESTAMP,
updated_at TIMESTAMP,
deleted_at TIMESTAMP,
UNIQUE (cgrid, runid)
);
CREATE INDEX deleted_at_cd_idx ON cost_details (deleted_at);
--
-- Table structure for table `rated_cdrs`
--
DROP TABLE IF EXISTS rated_cdrs;
CREATE TABLE rated_cdrs (
id SERIAL PRIMARY KEY,
cgrid CHAR(40) NOT NULL,
runid VARCHAR(64) NOT NULL,
reqtype VARCHAR(24) NOT NULL,
direction VARCHAR(8) NOT NULL,
tenant VARCHAR(64) NOT NULL,
category VARCHAR(32) NOT NULL,
account VARCHAR(128) NOT NULL,
subject VARCHAR(128) NOT NULL,
destination VARCHAR(128) NOT NULL,
setup_time TIMESTAMP NOT NULL,
pdd NUMERIC(12,9) NOT NULL,
answer_time TIMESTAMP NOT NULL,
usage NUMERIC(30,9) NOT NULL,
supplier VARCHAR(128) NOT NULL,
disconnect_cause VARCHAR(64) NOT NULL,
cost NUMERIC(20,4) DEFAULT NULL,
extra_info text,
created_at TIMESTAMP,
updated_at TIMESTAMP,
deleted_at TIMESTAMP,
UNIQUE (cgrid, runid)
);
CREATE INDEX deleted_at_rc_idx ON rated_cdrs (deleted_at);

View File

@@ -162,7 +162,7 @@ type TpAction struct {
Categories string `index:"6" re:""`
DestinationTags string `index:"7" re:"\*any|\w+\s*"`
RatingSubject string `index:"8" re:"\w+\s*"`
SharedGroups string `index:"9" re:"[0-9A-Za-z_;]*"`
SharedGroups string `index:"9" re:"[0-9A-Za-z_;]*"`
ExpiryTime string `index:"10" re:"\*\w+\s*|\+\d+[smh]\s*|\d+\s*"`
TimingTags string `index:"11" re:"[0-9A-Za-z_;]*|\*any"`
Units float64 `index:"12" re:"\d+\s*"`
@@ -197,7 +197,7 @@ type TpActionTrigger struct {
BalanceCategories string `index:"9" re:""`
BalanceDestinationTags string `index:"10" re:"\w+|\*any"`
BalanceRatingSubject string `index:"11" re:"\w+|\*any"`
BalanceSharedGroups string `index:"12" re:"\w+|\*any"`
BalanceSharedGroups string `index:"12" re:"\w+|\*any"`
BalanceExpiryTime string `index:"13" re:"\*\w+\s*|\+\d+[smh]\s*|\d+\s*"`
BalanceTimingTags string `index:"14" re:"[0-9A-Za-z_;]*|\*any"`
BalanceWeight float64 `index:"15" re:"\d+\.?\d*"`
@@ -390,9 +390,10 @@ func (ta *TpAlias) GetId() string {
return utils.ConcatenatedKey(ta.Direction, ta.Tenant, ta.Category, ta.Account, ta.Subject, ta.Context)
}
type TblCdrsPrimary struct {
type TblCdrs struct {
Id int64
Cgrid string
Runid string
Tor string
Accid string
Cdrhost string
@@ -410,73 +411,16 @@ type TblCdrsPrimary struct {
Usage float64
Supplier string
DisconnectCause string
CreatedAt time.Time
DeletedAt time.Time
}
func (t TblCdrsPrimary) TableName() string {
return utils.TBL_CDRS_PRIMARY
}
type TblCdrsExtra struct {
Id int64
Cgrid string
ExtraFields string
CreatedAt time.Time
DeletedAt time.Time
}
func (t TblCdrsExtra) TableName() string {
return utils.TBL_CDRS_EXTRA
}
type TblCostDetail struct {
Id int64
Cgrid string
Runid string
Tor string
Direction string
Tenant string
Category string
Account string
Subject string
Destination string
Cost float64
Timespans string
CostSource string
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt time.Time
}
func (t TblCostDetail) TableName() string {
return utils.TBL_COST_DETAILS
}
type TblRatedCdr struct {
Id int64
Cgrid string
Runid string
Reqtype string
Direction string
Tenant string
Category string
Account string
Subject string
Destination string
SetupTime time.Time
Pdd float64
AnswerTime time.Time
Usage float64
Supplier string
DisconnectCause string
ExtraFields string
Cost float64
Timespans string
CostSource string
ExtraInfo string
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt time.Time
}
func (t TblRatedCdr) TableName() string {
return utils.TBL_RATED_CDRS
func (t TblCdrs) TableName() string {
return utils.TBL_CDRS
}

View File

@@ -19,15 +19,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package engine
import (
"encoding/json"
"fmt"
"path"
"time"
"github.com/cgrates/cgrates/utils"
"github.com/jinzhu/gorm"
)
type MySQLStorage struct {
*SQLStorage
}
func NewMySQLStorage(host, port, name, user, password string, maxConn, maxIdleConn int) (*MySQLStorage, error) {
connectString := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8&loc=Local&parseTime=true", user, password, host, port, name)
db, err := gorm.Open("mysql", connectString)
@@ -43,81 +43,3 @@ func NewMySQLStorage(host, port, name, user, password string, maxConn, maxIdleCo
return &MySQLStorage{&SQLStorage{Db: db.DB(), db: db}}, nil
}
type MySQLStorage struct {
*SQLStorage
}
func (self *MySQLStorage) Flush(scriptsPath string) (err error) {
for _, scriptName := range []string{utils.CREATE_CDRS_TABLES_SQL, utils.CREATE_TARIFFPLAN_TABLES_SQL} {
if err := self.CreateTablesFromScript(path.Join(scriptsPath, scriptName)); err != nil {
return err
}
}
for _, tbl := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA} {
if _, err := self.Db.Query(fmt.Sprintf("SELECT 1 FROM %s", tbl)); err != nil {
return err
}
}
return nil
}
func (self *MySQLStorage) LogCallCost(cgrid, source, runid string, cc *CallCost) (err error) {
if cc == nil {
return nil
}
tss, err := json.Marshal(cc.Timespans)
if err != nil {
utils.Logger.Err(fmt.Sprintf("Error marshalling timespans to json: %v", err))
return err
}
_, err = self.Db.Exec(fmt.Sprintf("INSERT INTO %s (cgrid,runid,tor,direction,tenant,category,account,subject,destination,cost,timespans,cost_source,created_at) VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s',%f,'%s','%s','%s') ON DUPLICATE KEY UPDATE tor=values(tor),direction=values(direction),tenant=values(tenant),category=values(category),account=values(account),subject=values(subject),destination=values(destination),cost=values(cost),timespans=values(timespans),cost_source=values(cost_source),updated_at='%s'",
utils.TBL_COST_DETAILS,
cgrid,
runid,
cc.TOR,
cc.Direction,
cc.Tenant,
cc.Category,
cc.Account,
cc.Subject,
cc.Destination,
cc.Cost,
tss,
source,
time.Now().Format(time.RFC3339),
time.Now().Format(time.RFC3339)))
if err != nil {
utils.Logger.Err(fmt.Sprintf("failed to execute insert statement: %v", err))
return err
}
return nil
}
func (self *MySQLStorage) SetRatedCdr(storedCdr *StoredCdr) (err error) {
_, err = self.Db.Exec(fmt.Sprintf("INSERT INTO %s (cgrid,runid,reqtype,direction,tenant,category,account,subject,destination,setup_time,answer_time,`usage`,pdd,supplier,disconnect_cause,cost,extra_info,created_at) VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s',%v,%v,'%s','%s',%f,'%s','%s') ON DUPLICATE KEY UPDATE reqtype=values(reqtype),direction=values(direction),tenant=values(tenant),category=values(category),account=values(account),subject=values(subject),destination=values(destination),setup_time=values(setup_time),answer_time=values(answer_time),`usage`=values(`usage`),pdd=values(pdd),cost=values(cost),supplier=values(supplier),disconnect_cause=values(disconnect_cause),extra_info=values(extra_info), updated_at='%s'",
utils.TBL_RATED_CDRS,
storedCdr.CgrId,
storedCdr.MediationRunId,
storedCdr.ReqType,
storedCdr.Direction,
storedCdr.Tenant,
storedCdr.Category,
storedCdr.Account,
storedCdr.Subject,
storedCdr.Destination,
storedCdr.SetupTime,
storedCdr.AnswerTime,
storedCdr.Usage.Seconds(),
storedCdr.Pdd.Seconds(),
storedCdr.Supplier,
storedCdr.DisconnectCause,
storedCdr.Cost,
storedCdr.ExtraInfo,
time.Now().Format(time.RFC3339),
time.Now().Format(time.RFC3339)))
if err != nil {
utils.Logger.Err(fmt.Sprintf("failed to execute cdr insert statement: %s", err.Error()))
}
return
}

View File

@@ -48,10 +48,8 @@ func TestMySQLCreateTables(t *testing.T) {
return // No point in going further
}
}
for _, tbl := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA} {
if _, err := mysqlDb.Db.Query(fmt.Sprintf("SELECT 1 from %s", tbl)); err != nil {
t.Error(err.Error())
}
if _, err := mysqlDb.Db.Query(fmt.Sprintf("SELECT 1 from %s", utils.TBL_CDRS)); err != nil {
t.Error(err.Error())
}
}

View File

@@ -19,12 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package engine
import (
"encoding/json"
"fmt"
"path"
"time"
"github.com/cgrates/cgrates/utils"
"github.com/jinzhu/gorm"
_ "github.com/lib/pq"
@@ -50,97 +45,3 @@ func NewPostgresStorage(host, port, name, user, password string, maxConn, maxIdl
return &PostgresStorage{&SQLStorage{Db: db.DB(), db: db}}, nil
}
func (self *PostgresStorage) Flush(scriptsPath string) (err error) {
for _, scriptName := range []string{utils.CREATE_CDRS_TABLES_SQL, utils.CREATE_TARIFFPLAN_TABLES_SQL} {
if err := self.CreateTablesFromScript(path.Join(scriptsPath, scriptName)); err != nil {
return err
}
}
for _, tbl := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA} {
if _, err := self.Db.Query(fmt.Sprintf("SELECT 1 FROM %s", tbl)); err != nil {
return err
}
}
return nil
}
func (self *PostgresStorage) LogCallCost(cgrid, source, runid string, cc *CallCost) (err error) {
if cc == nil {
return nil
}
tss, err := json.Marshal(cc.Timespans)
if err != nil {
utils.Logger.Err(fmt.Sprintf("Error marshalling timespans to json: %v", err))
return err
}
tx := self.db.Begin()
cd := &TblCostDetail{
Cgrid: cgrid,
Runid: runid,
Tor: cc.TOR,
Direction: cc.Direction,
Tenant: cc.Tenant,
Category: cc.Category,
Account: cc.Account,
Subject: cc.Subject,
Destination: cc.Destination,
Cost: cc.Cost,
Timespans: string(tss),
CostSource: source,
CreatedAt: time.Now(),
}
if tx.Save(cd).Error != nil { // Check further since error does not properly reflect duplicates here (sql: no rows in result set)
tx.Rollback()
tx = self.db.Begin()
updated := tx.Model(TblCostDetail{}).Where(&TblCostDetail{Cgrid: cgrid, Runid: runid}).Updates(&TblCostDetail{Tor: cc.TOR, Direction: cc.Direction, Tenant: cc.Tenant, Category: cc.Category,
Account: cc.Account, Subject: cc.Subject, Destination: cc.Destination, Cost: cc.Cost, Timespans: string(tss), CostSource: source, UpdatedAt: time.Now()})
if updated.Error != nil {
tx.Rollback()
return updated.Error
}
}
tx.Commit()
return nil
}
func (self *PostgresStorage) SetRatedCdr(cdr *StoredCdr) (err error) {
tx := self.db.Begin()
saved := tx.Save(&TblRatedCdr{
Cgrid: cdr.CgrId,
Runid: cdr.MediationRunId,
Reqtype: cdr.ReqType,
Direction: cdr.Direction,
Tenant: cdr.Tenant,
Category: cdr.Category,
Account: cdr.Account,
Subject: cdr.Subject,
Destination: cdr.Destination,
SetupTime: cdr.SetupTime,
AnswerTime: cdr.AnswerTime,
Usage: cdr.Usage.Seconds(),
Pdd: cdr.Pdd.Seconds(),
Supplier: cdr.Supplier,
DisconnectCause: cdr.DisconnectCause,
Cost: cdr.Cost,
ExtraInfo: cdr.ExtraInfo,
CreatedAt: time.Now(),
})
if saved.Error != nil {
tx.Rollback()
tx = self.db.Begin()
updated := tx.Model(TblRatedCdr{}).Where(&TblRatedCdr{Cgrid: cdr.CgrId, Runid: cdr.MediationRunId}).Updates(&TblRatedCdr{Reqtype: cdr.ReqType,
Direction: cdr.Direction, Tenant: cdr.Tenant, Category: cdr.Category, Account: cdr.Account, Subject: cdr.Subject, Destination: cdr.Destination,
SetupTime: cdr.SetupTime, AnswerTime: cdr.AnswerTime, Usage: cdr.Usage.Seconds(), Pdd: cdr.Pdd.Seconds(), Supplier: cdr.Supplier, DisconnectCause: cdr.DisconnectCause,
Cost: cdr.Cost, ExtraInfo: cdr.ExtraInfo,
UpdatedAt: time.Now()})
if updated.Error != nil {
tx.Rollback()
return updated.Error
}
}
tx.Commit()
return nil
}

View File

@@ -48,10 +48,8 @@ func TestPSQLCreateTables(t *testing.T) {
return // No point in going further
}
}
for _, tbl := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA} {
if _, err := psqlDb.Db.Query(fmt.Sprintf("SELECT 1 from %s", tbl)); err != nil {
t.Error(err.Error())
}
if _, err := psqlDb.Db.Query(fmt.Sprintf("SELECT 1 from %s", utils.TBL_CDRS)); err != nil {
t.Error(err.Error())
}
}

View File

@@ -24,6 +24,7 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"path"
"strconv"
"strings"
"time"
@@ -43,8 +44,16 @@ func (self *SQLStorage) Close() {
self.db.Close()
}
func (self *SQLStorage) Flush(placeholder string) (err error) {
return utils.ErrNotImplemented
func (self *SQLStorage) Flush(scriptsPath string) (err error) {
for _, scriptName := range []string{utils.CREATE_CDRS_TABLES_SQL, utils.CREATE_TARIFFPLAN_TABLES_SQL} {
if err := self.CreateTablesFromScript(path.Join(scriptsPath, scriptName)); err != nil {
return err
}
}
if _, err := self.Db.Query(fmt.Sprintf("SELECT 1 FROM %s", utils.TBL_CDRS)); err != nil {
return err
}
return nil
}
func (self *SQLStorage) GetKeysForPrefix(prefix string) ([]string, error) {
@@ -561,14 +570,49 @@ func (self *SQLStorage) SetTpAccountActions(aas []TpAccountAction) error {
return nil
}
func (self *SQLStorage) LogCallCost(cgrid, source, runid string, cc *CallCost) (err error) {
if cc == nil {
return nil
}
tss, err := json.Marshal(cc.Timespans)
if err != nil {
utils.Logger.Err(fmt.Sprintf("Error marshalling timespans to json: %v", err))
return err
}
tx := self.db.Begin()
cd := &TblCdrs{
Cgrid: cgrid,
Runid: runid,
Tor: cc.TOR,
Direction: cc.Direction,
Tenant: cc.Tenant,
Category: cc.Category,
Account: cc.Account,
Subject: cc.Subject,
Destination: cc.Destination,
Cost: cc.Cost,
Timespans: string(tss),
CostSource: source,
CreatedAt: time.Now(),
}
func (self *SQLStorage) LogCallCost(cgrid, source, runid string, cc *CallCost) error {
return utils.ErrNotImplemented
if tx.Save(cd).Error != nil { // Check further since error does not properly reflect duplicates here (sql: no rows in result set)
tx.Rollback()
tx = self.db.Begin()
updated := tx.Model(TblCdrs{}).Where(&TblCdrs{Cgrid: cgrid, Runid: runid}).Updates(&TblCdrs{Tor: cc.TOR, Direction: cc.Direction, Tenant: cc.Tenant, Category: cc.Category,
Account: cc.Account, Subject: cc.Subject, Destination: cc.Destination, Cost: cc.Cost, Timespans: string(tss), CostSource: source, UpdatedAt: time.Now()})
if updated.Error != nil {
tx.Rollback()
return updated.Error
}
}
tx.Commit()
return nil
}
func (self *SQLStorage) GetCallCostLog(cgrid, source, runid string) (*CallCost, error) {
var tpCostDetail TblCostDetail
if err := self.db.Where(&TblCostDetail{Cgrid: cgrid, Runid: runid, CostSource: source}).First(&tpCostDetail).Error; err != nil {
var tpCostDetail TblCdrs
if err := self.db.Where(&TblCdrs{Cgrid: cgrid, Runid: runid, CostSource: source}).First(&tpCostDetail).Error; err != nil {
return nil, err
}
if len(tpCostDetail.Timespans) == 0 {
@@ -602,7 +646,7 @@ func (self *SQLStorage) SetCdr(cdr *StoredCdr) error {
return err
}
tx := self.db.Begin()
saved := tx.Save(&TblCdrsPrimary{
saved := tx.Save(&TblCdrs{
Cgrid: cdr.CgrId,
Tor: cdr.TOR,
Accid: cdr.AccId,
@@ -621,243 +665,184 @@ func (self *SQLStorage) SetCdr(cdr *StoredCdr) error {
Pdd: cdr.Pdd.Seconds(),
Supplier: cdr.Supplier,
DisconnectCause: cdr.DisconnectCause,
ExtraFields: string(extraFields),
CreatedAt: time.Now()})
if saved.Error != nil {
tx.Rollback()
return saved.Error
}
// Save extra fields
if err := tx.Save(&TblCdrsExtra{Cgrid: cdr.CgrId, ExtraFields: string(extraFields), CreatedAt: time.Now()}).Error; err != nil {
tx.Rollback()
return err
}
tx.Commit()
return nil
}
func (self *SQLStorage) SetRatedCdr(storedCdr *StoredCdr) error {
return utils.ErrNotImplemented
func (self *SQLStorage) SetRatedCdr(cdr *StoredCdr) (err error) {
tx := self.db.Begin()
saved := tx.Save(&TblCdrs{
Cgrid: cdr.CgrId,
Runid: cdr.MediationRunId,
Reqtype: cdr.ReqType,
Direction: cdr.Direction,
Tenant: cdr.Tenant,
Category: cdr.Category,
Account: cdr.Account,
Subject: cdr.Subject,
Destination: cdr.Destination,
SetupTime: cdr.SetupTime,
AnswerTime: cdr.AnswerTime,
Usage: cdr.Usage.Seconds(),
Pdd: cdr.Pdd.Seconds(),
Supplier: cdr.Supplier,
DisconnectCause: cdr.DisconnectCause,
Cost: cdr.Cost,
ExtraInfo: cdr.ExtraInfo,
CreatedAt: time.Now(),
})
if saved.Error != nil {
tx.Rollback()
tx = self.db.Begin()
updated := tx.Model(TblCdrs{}).Where(&TblCdrs{Cgrid: cdr.CgrId, Runid: cdr.MediationRunId}).Updates(&TblCdrs{Reqtype: cdr.ReqType,
Direction: cdr.Direction, Tenant: cdr.Tenant, Category: cdr.Category, Account: cdr.Account, Subject: cdr.Subject, Destination: cdr.Destination,
SetupTime: cdr.SetupTime, AnswerTime: cdr.AnswerTime, Usage: cdr.Usage.Seconds(), Pdd: cdr.Pdd.Seconds(), Supplier: cdr.Supplier, DisconnectCause: cdr.DisconnectCause,
Cost: cdr.Cost, ExtraInfo: cdr.ExtraInfo,
UpdatedAt: time.Now()})
if updated.Error != nil {
tx.Rollback()
return updated.Error
}
}
tx.Commit()
return nil
}
func (self *SQLStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*StoredCdr, int64, error) {
var cdrs []*StoredCdr
// Select string
var selectStr string
if qryFltr.FilterOnRated { // We use different tables to query account data in case of derived
selectStr = fmt.Sprintf("%s.cgrid,%s.id,%s.tor,%s.accid,%s.cdrhost,%s.cdrsource,%s.reqtype,%s.direction,%s.tenant,%s.category,%s.account,%s.subject,%s.destination,%s.setup_time,%s.answer_time,%s.usage,%s.pdd,%s.supplier,%s.disconnect_cause,%s.extra_fields,%s.runid,%s.cost,%s.tor,%s.direction,%s.tenant,%s.category,%s.account,%s.subject,%s.destination,%s.cost,%s.timespans",
utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS,
utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS,
utils.TBL_CDRS_EXTRA, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS,
utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS)
} else {
selectStr = fmt.Sprintf("%s.cgrid,%s.id,%s.tor,%s.accid,%s.cdrhost,%s.cdrsource,%s.reqtype,%s.direction,%s.tenant,%s.category,%s.account,%s.subject,%s.destination,%s.setup_time,%s.answer_time,%s.usage,%s.pdd,%s.supplier,%s.disconnect_cause,%s.extra_fields,%s.runid,%s.cost,%s.tor,%s.direction,%s.tenant,%s.category,%s.account,%s.subject,%s.destination,%s.cost,%s.timespans",
utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY,
utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY,
utils.TBL_CDRS_EXTRA, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS,
utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS)
}
// Join string
joinStr := fmt.Sprintf("LEFT JOIN %s ON %s.cgrid=%s.cgrid LEFT JOIN %s ON %s.cgrid=%s.cgrid LEFT JOIN %s ON %s.cgrid=%s.cgrid AND %s.runid=%s.runid", utils.TBL_CDRS_EXTRA, utils.TBL_CDRS_PRIMARY,
utils.TBL_CDRS_EXTRA, utils.TBL_RATED_CDRS, utils.TBL_CDRS_PRIMARY, utils.TBL_RATED_CDRS, utils.TBL_COST_DETAILS, utils.TBL_RATED_CDRS, utils.TBL_COST_DETAILS, utils.TBL_RATED_CDRS, utils.TBL_COST_DETAILS)
q := self.db.Table(utils.TBL_CDRS_PRIMARY).Select(selectStr).Joins(joinStr)
q := self.db.Table(utils.TBL_CDRS).Select("*")
if qryFltr.Unscoped {
q = q.Unscoped()
} else {
// Query filter
for _, tblName := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA, utils.TBL_COST_DETAILS, utils.TBL_RATED_CDRS} {
q = q.Where(fmt.Sprintf("(%s.deleted_at IS NULL OR %s.deleted_at <= '0001-01-02')", tblName, tblName)) // Soft deletes
}
q = q.Where("(deleted_at IS NULL OR deleted_at <= '0001-01-02')") // Soft deletes
}
// Add filters, use in to replace the high number of ORs
if len(qryFltr.CgrIds) != 0 {
q = q.Where(utils.TBL_CDRS_PRIMARY+".cgrid in (?)", qryFltr.CgrIds)
q = q.Where("cgrid in (?)", qryFltr.CgrIds)
}
if len(qryFltr.NotCgrIds) != 0 {
q = q.Where(utils.TBL_CDRS_PRIMARY+".cgrid not in (?)", qryFltr.NotCgrIds)
q = q.Where("cgrid not in (?)", qryFltr.NotCgrIds)
}
if len(qryFltr.RunIds) != 0 {
q = q.Where(utils.TBL_RATED_CDRS+".runid in (?)", qryFltr.RunIds)
q = q.Where("runid in (?)", qryFltr.RunIds)
}
if len(qryFltr.NotRunIds) != 0 {
q = q.Where(utils.TBL_RATED_CDRS+".runid not in (?)", qryFltr.NotRunIds)
q = q.Where("runid not in (?)", qryFltr.NotRunIds)
}
if len(qryFltr.Tors) != 0 {
q = q.Where(utils.TBL_CDRS_PRIMARY+".tor in (?)", qryFltr.Tors)
q = q.Where("tor in (?)", qryFltr.Tors)
}
if len(qryFltr.NotTors) != 0 {
q = q.Where(utils.TBL_CDRS_PRIMARY+".tor not in (?)", qryFltr.NotTors)
q = q.Where("tor not in (?)", qryFltr.NotTors)
}
if len(qryFltr.CdrHosts) != 0 {
q = q.Where(utils.TBL_CDRS_PRIMARY+".cdrhost in (?)", qryFltr.CdrHosts)
q = q.Where("cdrhost in (?)", qryFltr.CdrHosts)
}
if len(qryFltr.NotCdrHosts) != 0 {
q = q.Where(utils.TBL_CDRS_PRIMARY+".cdrhost not in (?)", qryFltr.NotCdrHosts)
q = q.Where("cdrhost not in (?)", qryFltr.NotCdrHosts)
}
if len(qryFltr.CdrSources) != 0 {
q = q.Where(utils.TBL_CDRS_PRIMARY+".cdrsource in (?)", qryFltr.CdrSources)
q = q.Where("cdrsource in (?)", qryFltr.CdrSources)
}
if len(qryFltr.NotCdrSources) != 0 {
q = q.Where(utils.TBL_CDRS_PRIMARY+".cdrsource not in (?)", qryFltr.NotCdrSources)
q = q.Where("cdrsource not in (?)", qryFltr.NotCdrSources)
}
if len(qryFltr.ReqTypes) != 0 {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".reqtype in (?)", qryFltr.ReqTypes)
q = q.Where("reqtype in (?)", qryFltr.ReqTypes)
}
if len(qryFltr.NotReqTypes) != 0 {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".reqtype not in (?)", qryFltr.NotReqTypes)
q = q.Where("reqtype not in (?)", qryFltr.NotReqTypes)
}
if len(qryFltr.Directions) != 0 {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".direction in (?)", qryFltr.Directions)
q = q.Where("direction in (?)", qryFltr.Directions)
}
if len(qryFltr.NotDirections) != 0 {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".direction not in (?)", qryFltr.NotDirections)
q = q.Where("direction not in (?)", qryFltr.NotDirections)
}
if len(qryFltr.Tenants) != 0 {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".tenant in (?)", qryFltr.Tenants)
q = q.Where("tenant in (?)", qryFltr.Tenants)
}
if len(qryFltr.NotTenants) != 0 {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".tenant not in (?)", qryFltr.NotTenants)
q = q.Where("tenant not in (?)", qryFltr.NotTenants)
}
if len(qryFltr.Categories) != 0 {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".category in (?)", qryFltr.Categories)
q = q.Where("category in (?)", qryFltr.Categories)
}
if len(qryFltr.NotCategories) != 0 {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".category not in (?)", qryFltr.NotCategories)
q = q.Where("category not in (?)", qryFltr.NotCategories)
}
if len(qryFltr.Accounts) != 0 {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".account in (?)", qryFltr.Accounts)
q = q.Where("account in (?)", qryFltr.Accounts)
}
if len(qryFltr.NotAccounts) != 0 {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".account not in (?)", qryFltr.NotAccounts)
q = q.Where("account not in (?)", qryFltr.NotAccounts)
}
if len(qryFltr.Subjects) != 0 {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".subject in (?)", qryFltr.Subjects)
q = q.Where("subject in (?)", qryFltr.Subjects)
}
if len(qryFltr.NotSubjects) != 0 {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".subject not in (?)", qryFltr.NotSubjects)
q = q.Where("subject not in (?)", qryFltr.NotSubjects)
}
if len(qryFltr.DestPrefixes) != 0 { // A bit ugly but still more readable than scopes provided by gorm
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
qIds := bytes.NewBufferString("(")
for idx, destPrefix := range qryFltr.DestPrefixes {
if idx != 0 {
qIds.WriteString(" OR")
}
qIds.WriteString(fmt.Sprintf(" %s.destination LIKE '%s%%'", tblName, destPrefix))
qIds.WriteString(fmt.Sprintf(" destination LIKE '%s%%'", destPrefix))
}
qIds.WriteString(" )")
q = q.Where(qIds.String())
}
if len(qryFltr.NotDestPrefixes) != 0 { // A bit ugly but still more readable than scopes provided by gorm
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
qIds := bytes.NewBufferString("(")
for idx, destPrefix := range qryFltr.NotDestPrefixes {
if idx != 0 {
qIds.WriteString(" AND")
}
qIds.WriteString(fmt.Sprintf(" %s.destination not LIKE '%%%s%%'", tblName, destPrefix))
qIds.WriteString(fmt.Sprintf(" destination not LIKE '%%%s%%'", destPrefix))
}
qIds.WriteString(" )")
q = q.Where(qIds.String())
}
if len(qryFltr.Suppliers) != 0 {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".supplier in (?)", qryFltr.Subjects)
q = q.Where("supplier in (?)", qryFltr.Subjects)
}
if len(qryFltr.NotSuppliers) != 0 {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".supplier not in (?)", qryFltr.NotSubjects)
q = q.Where("supplier not in (?)", qryFltr.NotSubjects)
}
if len(qryFltr.DisconnectCauses) != 0 {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".disconnect_cause in (?)", qryFltr.DisconnectCauses)
q = q.Where("disconnect_cause in (?)", qryFltr.DisconnectCauses)
}
if len(qryFltr.NotDisconnectCauses) != 0 {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".disconnect_cause not in (?)", qryFltr.NotDisconnectCauses)
q = q.Where("disconnect_cause not in (?)", qryFltr.NotDisconnectCauses)
}
if len(qryFltr.RatedAccounts) != 0 {
q = q.Where(utils.TBL_COST_DETAILS+".account in (?)", qryFltr.RatedAccounts)
q = q.Where(utils.TBL_CDRS+".account in (?)", qryFltr.RatedAccounts)
}
if len(qryFltr.NotRatedAccounts) != 0 {
q = q.Where(utils.TBL_COST_DETAILS+".account not in (?)", qryFltr.NotRatedAccounts)
q = q.Where(utils.TBL_CDRS+".account not in (?)", qryFltr.NotRatedAccounts)
}
if len(qryFltr.RatedSubjects) != 0 {
q = q.Where(utils.TBL_COST_DETAILS+".subject in (?)", qryFltr.RatedSubjects)
q = q.Where(utils.TBL_CDRS+".subject in (?)", qryFltr.RatedSubjects)
}
if len(qryFltr.NotRatedSubjects) != 0 {
q = q.Where(utils.TBL_COST_DETAILS+".subject not in (?)", qryFltr.NotRatedSubjects)
q = q.Where(utils.TBL_CDRS+".subject not in (?)", qryFltr.NotRatedSubjects)
}
if len(qryFltr.Costs) != 0 {
q = q.Where(utils.TBL_RATED_CDRS+".cost in (?)", qryFltr.Costs)
q = q.Where(utils.TBL_CDRS+".cost in (?)", qryFltr.Costs)
}
if len(qryFltr.NotCosts) != 0 {
q = q.Where(utils.TBL_RATED_CDRS+".cost not in (?)", qryFltr.NotCosts)
q = q.Where(utils.TBL_CDRS+".cost not in (?)", qryFltr.NotCosts)
}
if len(qryFltr.ExtraFields) != 0 { // Extra fields searches, implemented as contains in extra field
qIds := bytes.NewBufferString("(")
@@ -866,7 +851,7 @@ func (self *SQLStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*StoredCdr,
if needOr {
qIds.WriteString(" OR")
}
qIds.WriteString(fmt.Sprintf(` %s.extra_fields LIKE '%%"%s":"%s"%%'`, utils.TBL_CDRS_EXTRA, field, value))
qIds.WriteString(fmt.Sprintf(` extra_fields LIKE '%%"%s":"%s"%%'`, field, value))
needOr = true
}
qIds.WriteString(" )")
@@ -879,117 +864,69 @@ func (self *SQLStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*StoredCdr,
if needAnd {
qIds.WriteString(" OR")
}
qIds.WriteString(fmt.Sprintf(` %s.extra_fields LIKE '%%"%s":"%s"%%'`, utils.TBL_CDRS_EXTRA, field, value))
qIds.WriteString(fmt.Sprintf(` extra_fields LIKE '%%"%s":"%s"%%'`, field, value))
needAnd = true
}
qIds.WriteString(" )")
q = q.Where(qIds.String())
}
if qryFltr.OrderIdStart != 0 { // Keep backwards compatible by testing 0 value
q = q.Where(utils.TBL_CDRS_PRIMARY+".id >= ?", qryFltr.OrderIdStart)
q = q.Where(utils.TBL_CDRS+".id >= ?", qryFltr.OrderIdStart)
}
if qryFltr.OrderIdEnd != 0 {
q = q.Where(utils.TBL_CDRS_PRIMARY+".id < ?", qryFltr.OrderIdEnd)
q = q.Where(utils.TBL_CDRS+".id < ?", qryFltr.OrderIdEnd)
}
if qryFltr.SetupTimeStart != nil {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".setup_time >= ?", qryFltr.SetupTimeStart)
q = q.Where("setup_time >= ?", qryFltr.SetupTimeStart)
}
if qryFltr.SetupTimeEnd != nil {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".setup_time < ?", qryFltr.SetupTimeEnd)
q = q.Where("setup_time < ?", qryFltr.SetupTimeEnd)
}
if qryFltr.AnswerTimeStart != nil && !qryFltr.AnswerTimeStart.IsZero() { // With IsZero we keep backwards compatible with ApierV1
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".answer_time >= ?", qryFltr.AnswerTimeStart)
q = q.Where("answer_time >= ?", qryFltr.AnswerTimeStart)
}
if qryFltr.AnswerTimeEnd != nil && !qryFltr.AnswerTimeEnd.IsZero() {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".answer_time < ?", qryFltr.AnswerTimeEnd)
q = q.Where("answer_time < ?", qryFltr.AnswerTimeEnd)
}
if qryFltr.CreatedAtStart != nil && !qryFltr.CreatedAtStart.IsZero() { // With IsZero we keep backwards compatible with ApierV1
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".created_at >= ?", qryFltr.CreatedAtStart)
q = q.Where("created_at >= ?", qryFltr.CreatedAtStart)
}
if qryFltr.CreatedAtEnd != nil && !qryFltr.CreatedAtEnd.IsZero() {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".created_at < ?", qryFltr.CreatedAtEnd)
q = q.Where("created_at < ?", qryFltr.CreatedAtEnd)
}
if qryFltr.UpdatedAtStart != nil && !qryFltr.UpdatedAtStart.IsZero() { // With IsZero we keep backwards compatible with ApierV1
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".updated_at >= ?", qryFltr.UpdatedAtStart)
q = q.Where("updated_at >= ?", qryFltr.UpdatedAtStart)
}
if qryFltr.UpdatedAtEnd != nil && !qryFltr.UpdatedAtEnd.IsZero() {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".updated_at < ?", qryFltr.UpdatedAtEnd)
q = q.Where("updated_at < ?", qryFltr.UpdatedAtEnd)
}
if qryFltr.MinUsage != nil {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".usage >= ?", qryFltr.MinUsage)
q = q.Where("usage >= ?", qryFltr.MinUsage)
}
if qryFltr.MaxUsage != nil {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".usage < ?", qryFltr.MaxUsage)
q = q.Where("usage < ?", qryFltr.MaxUsage)
}
if qryFltr.MinPdd != nil {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".pdd >= ?", qryFltr.MinPdd)
q = q.Where("pdd >= ?", qryFltr.MinPdd)
}
if qryFltr.MaxPdd != nil {
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
q = q.Where(tblName+".pdd < ?", qryFltr.MaxPdd)
q = q.Where("pdd < ?", qryFltr.MaxPdd)
}
if qryFltr.MinCost != nil {
if qryFltr.MaxCost == nil {
q = q.Where(utils.TBL_RATED_CDRS+".cost >= ?", *qryFltr.MinCost)
q = q.Where("cost >= ?", *qryFltr.MinCost)
} else if *qryFltr.MinCost == 0.0 && *qryFltr.MaxCost == -1.0 { // Special case when we want to skip errors
q = q.Where(fmt.Sprintf("( %s.cost IS NULL OR %s.cost >= 0.0 )", utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS))
q = q.Where("( cost IS NULL OR cost >= 0.0 )")
} else {
q = q.Where(utils.TBL_RATED_CDRS+".cost >= ?", *qryFltr.MinCost)
q = q.Where(utils.TBL_RATED_CDRS+".cost < ?", *qryFltr.MaxCost)
q = q.Where("cost >= ?", *qryFltr.MinCost)
q = q.Where("cost < ?", *qryFltr.MaxCost)
}
} else if qryFltr.MaxCost != nil {
if *qryFltr.MaxCost == -1.0 { // Non-rated CDRs
q = q.Where(utils.TBL_RATED_CDRS + ".cost IS NULL") // Need to include it otherwise all CDRs will be returned
q = q.Where("cost IS NULL") // Need to include it otherwise all CDRs will be returned
} else { // Above limited CDRs, since MinCost is empty, make sure we query also NULL cost
q = q.Where(fmt.Sprintf("( %s.cost IS NULL OR %s.cost < %f )", utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, *qryFltr.MaxCost))
q = q.Where(fmt.Sprintf("( cost IS NULL OR cost < %f )", *qryFltr.MaxCost))
}
}
if qryFltr.Paginator.Limit != nil {
@@ -1057,353 +994,25 @@ func (self *SQLStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*StoredCdr,
return cdrs, 0, nil
}
/*func (self *SQLStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*StoredCdr, int64, error) {
var cdrs []*StoredCdr
// Select string
var selectStr string
if qryFltr.FilterOnRated { // We use different tables to query account data in case of derived
selectTmpl := template.Must(template.New("select").Parse("{{.Pr}}.cgrid,{{.Pr}}.id,{{.Pr}}.tor,{{.Pr}}.accid,{{.Pr}}.cdrhost,{{.Pr}}.cdrsource,{{.Rc}}.reqtype,{{.Rc}}.direction,{{.Rc}}.tenant,{{.Rc}}.category,{{.Rc}}.account,{{.Rc}}.subject,{{.Rc}}.destination,{{.Rc}}.setup_time,{{.Rc}}.answer_time,{{.Rc}}.usage,{{.Rc}}.pdd,{{.Rc}}.supplier,{{.Rc}}.disconnect_cause,{{.Ex}}.extra_fields,{{.Rc}}.runid,{{.Rc}}.cost,{{.Cd}}.tor,{{.Cd}}.direction,{{.Cd}}.tenant,{{.Cd}}.category,{{.Cd}}.account,{{.Cd}}.subject,{{.Cd}}.destination,{{.Cd}}.cost,{{.Cd}}.timespans"))
var selectBuf bytes.Buffer
selectTmpl.Execute(&selectBuf, &struct {
Pr string
Ex string
Rc string
Cd string
}{utils.TBL_CDRS_PRIMARY,
utils.TBL_CDRS_EXTRA,
utils.TBL_RATED_CDRS,
utils.TBL_COST_DETAILS})
selectStr = selectBuf.String()
} else {
selectTmpl := template.Must(template.New("select").Parse("{{.Pr}}.cgrid,{{.Pr}}.id,{{.Pr}}.tor,{{.Pr}}.accid,{{.Pr}}.cdrhost,{{.Pr}}.cdrsource,{{.Pr}}.reqtype,{{.Pr}}.direction,{{.Pr}}.tenant,{{.Pr}}.category,{{.Pr}}.account,{{.Pr}}.subject,{{.Pr}}.destination,{{.Pr}}.setup_time,{{.Pr}}.answer_time,{{.Pr}}.usage,{{.Pr}}.pdd,{{.Pr}}.supplier,{{.Pr}}.disconnect_cause,{{.Ex}}.extra_fields,{{.Rc}}.runid,{{.Rc}}.cost,{{.Cd}}.tor,{{.Cd}}.direction,{{.Cd}}.tenant,{{.Cd}}.category,{{.Cd}}.account,{{.Cd}}.subject,{{.Cd}}.destination,{{.Cd}}.cost,{{.Cd}}.timespans"))
var selectBuf bytes.Buffer
selectTmpl.Execute(&selectBuf, &struct {
Pr string
Ex string
Rc string
Cd string
}{utils.TBL_CDRS_PRIMARY,
utils.TBL_CDRS_EXTRA,
utils.TBL_RATED_CDRS,
utils.TBL_COST_DETAILS})
selectStr = selectBuf.String()
}
// Join string
selectTmpl := template.Must(template.New("join").Parse("LEFT JOIN {{.Ex}} ON {{.Pr}}.cgrid={{.Ex}}.cgrid LEFT JOIN {{.Rc}} ON {{.Pr}}.cgrid={{.Rc}}.cgrid LEFT JOIN {{.Cd}} ON {{.Rc}}.cgrid={{.Cd}}.cgrid AND {{.Rc}}.runid={{.Cd}}.runid"))
var joinBuf bytes.Buffer
selectTmpl.Execute(&joinBuf, &struct {
Pr string
Ex string
Rc string
Cd string
}{utils.TBL_CDRS_PRIMARY,
utils.TBL_CDRS_EXTRA,
utils.TBL_RATED_CDRS,
utils.TBL_COST_DETAILS})
joinStr := joinBuf.String()
q := self.db.Table(utils.TBL_CDRS_PRIMARY).Select(selectStr).Joins(joinStr)
if qryFltr.Unscoped {
q = q.Unscoped()
} else {
// Query filter
for _, tblName := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA, utils.TBL_COST_DETAILS, utils.TBL_RATED_CDRS} {
q = q.Where(fmt.Sprintf("(%s.deleted_at IS NULL OR %s.deleted_at <= '0001-01-02')", tblName, tblName)) // Soft deletes
}
}
tblName := utils.TBL_CDRS_PRIMARY
if qryFltr.FilterOnRated {
tblName = utils.TBL_RATED_CDRS
}
// Add filters, use in to replace the high number of ORs
if len(qryFltr.CgrIds) != 0 {
q = q.Where(utils.TBL_CDRS_PRIMARY+".cgrid in (?)", qryFltr.CgrIds)
}
if len(qryFltr.NotCgrIds) != 0 {
q = q.Where(utils.TBL_CDRS_PRIMARY+".cgrid not in (?)", qryFltr.NotCgrIds)
}
if len(qryFltr.RunIds) != 0 {
q = q.Where(utils.TBL_RATED_CDRS+".runid in (?)", qryFltr.RunIds)
}
if len(qryFltr.NotRunIds) != 0 {
q = q.Where(utils.TBL_RATED_CDRS+".runid not in (?)", qryFltr.NotRunIds)
}
if len(qryFltr.Tors) != 0 {
q = q.Where(utils.TBL_CDRS_PRIMARY+".tor in (?)", qryFltr.Tors)
}
if len(qryFltr.NotTors) != 0 {
q = q.Where(utils.TBL_CDRS_PRIMARY+".tor not in (?)", qryFltr.NotTors)
}
if len(qryFltr.CdrHosts) != 0 {
q = q.Where(utils.TBL_CDRS_PRIMARY+".cdrhost in (?)", qryFltr.CdrHosts)
}
if len(qryFltr.NotCdrHosts) != 0 {
q = q.Where(utils.TBL_CDRS_PRIMARY+".cdrhost not in (?)", qryFltr.NotCdrHosts)
}
if len(qryFltr.CdrSources) != 0 {
q = q.Where(utils.TBL_CDRS_PRIMARY+".cdrsource in (?)", qryFltr.CdrSources)
}
if len(qryFltr.NotCdrSources) != 0 {
q = q.Where(utils.TBL_CDRS_PRIMARY+".cdrsource not in (?)", qryFltr.NotCdrSources)
}
if len(qryFltr.ReqTypes) != 0 {
q = q.Where(tblName+".reqtype in (?)", qryFltr.ReqTypes)
}
if len(qryFltr.NotReqTypes) != 0 {
q = q.Where(tblName+".reqtype not in (?)", qryFltr.NotReqTypes)
}
if len(qryFltr.Directions) != 0 {
q = q.Where(tblName+".direction in (?)", qryFltr.Directions)
}
if len(qryFltr.NotDirections) != 0 {
q = q.Where(tblName+".direction not in (?)", qryFltr.NotDirections)
}
if len(qryFltr.Tenants) != 0 {
q = q.Where(tblName+".tenant in (?)", qryFltr.Tenants)
}
if len(qryFltr.NotTenants) != 0 {
q = q.Where(tblName+".tenant not in (?)", qryFltr.NotTenants)
}
if len(qryFltr.Categories) != 0 {
q = q.Where(tblName+".category in (?)", qryFltr.Categories)
}
if len(qryFltr.NotCategories) != 0 {
q = q.Where(tblName+".category not in (?)", qryFltr.NotCategories)
}
if len(qryFltr.Accounts) != 0 {
q = q.Where(tblName+".account in (?)", qryFltr.Accounts)
}
if len(qryFltr.NotAccounts) != 0 {
q = q.Where(tblName+".account not in (?)", qryFltr.NotAccounts)
}
if len(qryFltr.Subjects) != 0 {
q = q.Where(tblName+".subject in (?)", qryFltr.Subjects)
}
if len(qryFltr.NotSubjects) != 0 {
q = q.Where(tblName+".subject not in (?)", qryFltr.NotSubjects)
}
if len(qryFltr.DestPrefixes) != 0 { // A bit ugly but still more readable than scopes provided by gorm
qIds := bytes.NewBufferString("(")
for idx, destPrefix := range qryFltr.DestPrefixes {
if idx != 0 {
qIds.WriteString(" OR")
}
qIds.WriteString(fmt.Sprintf(" %s.destination LIKE '%s%%'", tblName, destPrefix))
}
qIds.WriteString(" )")
q = q.Where(qIds.String())
}
if len(qryFltr.NotDestPrefixes) != 0 { // A bit ugly but still more readable than scopes provided by gorm
qIds := bytes.NewBufferString("(")
for idx, destPrefix := range qryFltr.NotDestPrefixes {
if idx != 0 {
qIds.WriteString(" AND")
}
qIds.WriteString(fmt.Sprintf(" %s.destination not LIKE '%%%s%%'", tblName, destPrefix))
}
qIds.WriteString(" )")
q = q.Where(qIds.String())
}
if len(qryFltr.Suppliers) != 0 {
q = q.Where(tblName+".supplier in (?)", qryFltr.Subjects)
}
if len(qryFltr.NotSuppliers) != 0 {
q = q.Where(tblName+".supplier not in (?)", qryFltr.NotSubjects)
}
if len(qryFltr.DisconnectCauses) != 0 {
q = q.Where(tblName+".disconnect_cause in (?)", qryFltr.DisconnectCauses)
}
if len(qryFltr.NotDisconnectCauses) != 0 {
q = q.Where(tblName+".disconnect_cause not in (?)", qryFltr.NotDisconnectCauses)
}
if len(qryFltr.RatedAccounts) != 0 {
q = q.Where(utils.TBL_COST_DETAILS+".account in (?)", qryFltr.RatedAccounts)
}
if len(qryFltr.NotRatedAccounts) != 0 {
q = q.Where(utils.TBL_COST_DETAILS+".account not in (?)", qryFltr.NotRatedAccounts)
}
if len(qryFltr.RatedSubjects) != 0 {
q = q.Where(utils.TBL_COST_DETAILS+".subject in (?)", qryFltr.RatedSubjects)
}
if len(qryFltr.NotRatedSubjects) != 0 {
q = q.Where(utils.TBL_COST_DETAILS+".subject not in (?)", qryFltr.NotRatedSubjects)
}
if len(qryFltr.Costs) != 0 {
q = q.Where(utils.TBL_RATED_CDRS+".cost in (?)", qryFltr.Costs)
}
if len(qryFltr.NotCosts) != 0 {
q = q.Where(utils.TBL_RATED_CDRS+".cost not in (?)", qryFltr.NotCosts)
}
if len(qryFltr.ExtraFields) != 0 { // Extra fields searches, implemented as contains in extra field
qIds := bytes.NewBufferString("(")
needOr := false
for field, value := range qryFltr.ExtraFields {
if needOr {
qIds.WriteString(" OR")
}
qIds.WriteString(fmt.Sprintf(` %s.extra_fields LIKE '%%"%s":"%s"%%'`, utils.TBL_CDRS_EXTRA, field, value))
needOr = true
}
qIds.WriteString(" )")
q = q.Where(qIds.String())
}
if len(qryFltr.NotExtraFields) != 0 { // Extra fields searches, implemented as contains in extra field
qIds := bytes.NewBufferString("(")
needAnd := false
for field, value := range qryFltr.NotExtraFields {
if needAnd {
qIds.WriteString(" OR")
}
qIds.WriteString(fmt.Sprintf(` %s.extra_fields LIKE '%%"%s":"%s"%%'`, utils.TBL_CDRS_EXTRA, field, value))
needAnd = true
}
qIds.WriteString(" )")
q = q.Where(qIds.String())
}
if qryFltr.OrderIdStart != 0 { // Keep backwards compatible by testing 0 value
q = q.Where(utils.TBL_CDRS_PRIMARY+".id >= ?", qryFltr.OrderIdStart)
}
if qryFltr.OrderIdEnd != 0 {
q = q.Where(utils.TBL_CDRS_PRIMARY+".id < ?", qryFltr.OrderIdEnd)
}
if qryFltr.SetupTimeStart != nil {
q = q.Where(tblName+".setup_time >= ?", qryFltr.SetupTimeStart)
}
if qryFltr.SetupTimeEnd != nil {
q = q.Where(tblName+".setup_time < ?", qryFltr.SetupTimeEnd)
}
if qryFltr.AnswerTimeStart != nil && !qryFltr.AnswerTimeStart.IsZero() { // With IsZero we keep backwards compatible with ApierV1
q = q.Where(tblName+".answer_time >= ?", qryFltr.AnswerTimeStart)
}
if qryFltr.AnswerTimeEnd != nil && !qryFltr.AnswerTimeEnd.IsZero() {
q = q.Where(tblName+".answer_time < ?", qryFltr.AnswerTimeEnd)
}
if qryFltr.CreatedAtStart != nil && !qryFltr.CreatedAtStart.IsZero() { // With IsZero we keep backwards compatible with ApierV1
q = q.Where(tblName+".created_at >= ?", qryFltr.CreatedAtStart)
}
if qryFltr.CreatedAtEnd != nil && !qryFltr.CreatedAtEnd.IsZero() {
q = q.Where(tblName+".created_at < ?", qryFltr.CreatedAtEnd)
}
if qryFltr.UpdatedAtStart != nil && !qryFltr.UpdatedAtStart.IsZero() { // With IsZero we keep backwards compatible with ApierV1
q = q.Where(tblName+".updated_at >= ?", qryFltr.UpdatedAtStart)
}
if qryFltr.UpdatedAtEnd != nil && !qryFltr.UpdatedAtEnd.IsZero() {
q = q.Where(tblName+".updated_at < ?", qryFltr.UpdatedAtEnd)
}
if qryFltr.MinUsage != nil {
q = q.Where(tblName+".usage >= ?", qryFltr.MinUsage)
}
if qryFltr.MaxUsage != nil {
q = q.Where(tblName+".usage < ?", qryFltr.MaxUsage)
}
if qryFltr.MinPdd != nil {
q = q.Where(tblName+".pdd >= ?", qryFltr.MinPdd)
}
if qryFltr.MaxPdd != nil {
q = q.Where(tblName+".pdd < ?", qryFltr.MaxPdd)
}
if qryFltr.MinCost != nil {
if qryFltr.MaxCost == nil {
q = q.Where(utils.TBL_RATED_CDRS+".cost >= ?", *qryFltr.MinCost)
} else if *qryFltr.MinCost == 0.0 && *qryFltr.MaxCost == -1.0 { // Special case when we want to skip errors
q = q.Where(fmt.Sprintf("( %s.cost IS NULL OR %s.cost >= 0.0 )", utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS))
} else {
q = q.Where(utils.TBL_RATED_CDRS+".cost >= ?", *qryFltr.MinCost)
q = q.Where(utils.TBL_RATED_CDRS+".cost < ?", *qryFltr.MaxCost)
}
} else if qryFltr.MaxCost != nil {
if *qryFltr.MaxCost == -1.0 { // Non-rated CDRs
q = q.Where(utils.TBL_RATED_CDRS + ".cost IS NULL") // Need to include it otherwise all CDRs will be returned
} else { // Above limited CDRs, since MinCost is empty, make sure we query also NULL cost
q = q.Where(fmt.Sprintf("( %s.cost IS NULL OR %s.cost < %f )", utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, *qryFltr.MaxCost))
}
}
if qryFltr.Paginator.Limit != nil {
q = q.Limit(*qryFltr.Paginator.Limit)
}
if qryFltr.Paginator.Offset != nil {
q = q.Offset(*qryFltr.Paginator.Offset)
}
if qryFltr.Count {
var cnt int64
if err := q.Count(&cnt).Error; err != nil {
//if err := q.Debug().Count(&cnt).Error; err != nil {
return nil, 0, err
}
return nil, cnt, nil
}
// Execute query
rows, err := q.Rows()
if err != nil {
return nil, 0, err
}
for rows.Next() {
var cgrid, tor, accid, cdrhost, cdrsrc, reqtype, direction, tenant, category, account, subject, destination, runid, ccTor,
ccDirection, ccTenant, ccCategory, ccAccount, ccSubject, ccDestination, ccSupplier, ccDisconnectCause sql.NullString
var extraFields, ccTimespansBytes []byte
var setupTime, answerTime mysql.NullTime
var orderid int64
var usage, pdd, cost, ccCost sql.NullFloat64
var extraFieldsMp map[string]string
var ccTimespans TimeSpans
if err := rows.Scan(&cgrid, &orderid, &tor, &accid, &cdrhost, &cdrsrc, &reqtype, &direction, &tenant, &category, &account, &subject, &destination,
&setupTime, &answerTime, &usage, &pdd, &ccSupplier, &ccDisconnectCause,
&extraFields, &runid, &cost, &ccTor, &ccDirection, &ccTenant, &ccCategory, &ccAccount, &ccSubject, &ccDestination, &ccCost, &ccTimespansBytes); err != nil {
return nil, 0, err
}
if len(extraFields) != 0 {
if err := json.Unmarshal(extraFields, &extraFieldsMp); err != nil {
return nil, 0, fmt.Errorf("JSON unmarshal error for cgrid: %s, runid: %v, error: %s", cgrid.String, runid.String, err.Error())
}
}
if len(ccTimespansBytes) != 0 {
if err := json.Unmarshal(ccTimespansBytes, &ccTimespans); err != nil {
return nil, 0, fmt.Errorf("JSON unmarshal callcost error for cgrid: %s, runid: %v, error: %s", cgrid.String, runid.String, err.Error())
}
}
usageDur, _ := time.ParseDuration(strconv.FormatFloat(usage.Float64, 'f', -1, 64) + "s")
pddDur, _ := time.ParseDuration(strconv.FormatFloat(pdd.Float64, 'f', -1, 64) + "s")
storCdr := &StoredCdr{
CgrId: cgrid.String, OrderId: orderid, TOR: tor.String, AccId: accid.String, CdrHost: cdrhost.String, CdrSource: cdrsrc.String, ReqType: reqtype.String,
Direction: direction.String, Tenant: tenant.String,
Category: category.String, Account: account.String, Subject: subject.String, Destination: destination.String,
SetupTime: setupTime.Time, AnswerTime: answerTime.Time, Usage: usageDur, Pdd: pddDur, Supplier: ccSupplier.String, DisconnectCause: ccDisconnectCause.String,
ExtraFields: extraFieldsMp, MediationRunId: runid.String, RatedAccount: ccAccount.String, RatedSubject: ccSubject.String, Cost: cost.Float64,
}
if ccTimespans != nil {
storCdr.CostDetails = &CallCost{Direction: ccDirection.String, Category: ccCategory.String, Tenant: ccTenant.String, Subject: ccSubject.String, Account: ccAccount.String, Destination: ccDestination.String, TOR: ccTor.String,
Cost: ccCost.Float64, Timespans: ccTimespans}
}
if !cost.Valid { //There was no cost provided, will fakely insert 0 if we do not handle it and reflect on re-rating
storCdr.Cost = -1
}
cdrs = append(cdrs, storCdr)
}
return cdrs, 0, nil
}
*/
// Remove CDR data out of all CDR tables based on their cgrid
func (self *SQLStorage) RemStoredCdrs(cgrIds []string) error {
if len(cgrIds) == 0 {
return nil
}
tx := self.db.Begin()
for _, tblName := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA, utils.TBL_COST_DETAILS, utils.TBL_RATED_CDRS} {
txI := tx.Table(tblName)
for idx, cgrId := range cgrIds {
if idx == 0 {
txI = txI.Where("cgrid = ?", cgrId)
} else {
txI = txI.Or("cgrid = ?", cgrId)
}
}
if err := txI.Update("deleted_at", time.Now()).Error; err != nil {
tx.Rollback()
return err
txI := tx.Table(utils.TBL_CDRS)
for idx, cgrId := range cgrIds {
if idx == 0 {
txI = txI.Where("cgrid = ?", cgrId)
} else {
txI = txI.Or("cgrid = ?", cgrId)
}
}
if err := txI.Update("deleted_at", time.Now()).Error; err != nil {
tx.Rollback()
return err
}
tx.Commit()
return nil
}

View File

@@ -92,10 +92,8 @@ func TestEmptyTables(t *testing.T) {
t.Fatal("Error on mysql creation: ", err.Error())
return // No point in going further
}
for _, tbl := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA} {
if _, err := mysql.Db.Query(fmt.Sprintf("SELECT 1 from %s", tbl)); err != nil {
t.Fatal(err.Error())
}
if _, err := mysql.Db.Query(fmt.Sprintf("SELECT 1 from %s", utils.TBL_CDRS)); err != nil {
t.Fatal(err.Error())
}
}

View File

@@ -62,10 +62,7 @@ const (
TBL_TP_DERIVED_CHARGERS = "tp_derived_chargers"
TBL_TP_USERS = "tp_users"
TBL_TP_ALIASES = "tp_aliases"
TBL_CDRS_PRIMARY = "cdrs_primary"
TBL_CDRS_EXTRA = "cdrs_extra"
TBL_COST_DETAILS = "cost_details"
TBL_RATED_CDRS = "rated_cdrs"
TBL_CDRS = "cdrs"
TIMINGS_CSV = "Timings.csv"
DESTINATIONS_CSV = "Destinations.csv"
RATES_CSV = "Rates.csv"