Browse Source

Updated.

develop
Mingcai SHEN 8 years ago
parent
commit
ab8af3d6ac
7 changed files with 285 additions and 283 deletions
  1. +14
    -14
      models/published/vod.go
  2. +26
    -26
      models/query.go
  3. +0
    -243
      models/types.go
  4. +1
    -0
      xql/query.go
  5. +1
    -0
      xql/session.go
  6. +0
    -0
      xql/table.go
  7. +243
    -0
      xql/types.go

+ 14
- 14
models/published/vod.go View File

@ -5,7 +5,7 @@ import (
"encoding/json"
"database/sql/driver"
"time"
"bitbucket.org/cygnux/kepler/models"
"bitbucket.org/cygnux/kepler/xql"
)
//type HStore map[string]string
@ -71,14 +71,14 @@ type VodAlbum struct {
PublishTime *time.Time `json:"publishTime,omitempty"`
Score float32 `json:"score,omitempty"`
ProviderName string `json:"providerName,omitempty"`
Categories models.HSTOREDictionary `json:"categories,omitempty"`
Tags models.StringArray `json:"tags,omitempty"`
Geniuses models.StringArray `json:"geniuses,omitempty"`
Crews models.JASONDictionary `json:"crews,omitempty"`
Videos models.JSONDictionaryArray `json:"videos,omitempty"`
ScreenShots models.StringArray `json:"screenShots,omitempty"`
VIPInfo models.JASONDictionary `json:"vipInfo,omitempty"`
PlayControl models.JASONDictionary `json:"playCtrl,omitempty"`
Categories xql.HSTOREDictionary `json:"categories,omitempty"`
Tags xql.StringArray `json:"tags,omitempty"`
Geniuses xql.StringArray `json:"geniuses,omitempty"`
Crews xql.JASONDictionary `json:"crews,omitempty"`
Videos xql.JSONDictionaryArray `json:"videos,omitempty"`
ScreenShots xql.StringArray `json:"screenShots,omitempty"`
VIPInfo xql.JASONDictionary `json:"vipInfo,omitempty"`
PlayControl xql.JASONDictionary `json:"playCtrl,omitempty"`
Description string `json:"description,omitempty"`
Created *time.Time `json:"created,omitempty"`
Updated *time.Time `json:"updated,omitempty"`
@ -98,10 +98,10 @@ type VodFilm struct {
Remark string `json:"remark"`
Language string `json:"language"`
IssueDate string `json:"issueDate,omitempty"`
PlayControl models.JASONDictionary `json:"playCtrl,omitempty"`
Crews models.JASONDictionary `json:"crews,omitempty"`
Videos models.JSONDictionaryArray `json:"videos,omitempty"`
ScreenShots models.StringArray `json:"screenShots,omitempty"`
PlayControl xql.JASONDictionary `json:"playCtrl,omitempty"`
Crews xql.JASONDictionary `json:"crews,omitempty"`
Videos xql.JSONDictionaryArray `json:"videos,omitempty"`
ScreenShots xql.StringArray `json:"screenShots,omitempty"`
Description string `json:"description,omitempty"`
Created *time.Time `json:"created,omitempty"`
Updated *time.Time `json:"updated,omitempty"`
@ -113,6 +113,6 @@ type VodRecommendAlbum struct {
Score float32 `json:"score,omitempty"`
Remark string `json:"remark"`
Poster string `json:"poster"`
Categories models.HSTOREDictionary `json:"categories"`
Categories xql.HSTOREDictionary `json:"categories"`
}

+ 26
- 26
models/query.go View File

@ -1,29 +1,29 @@
package models
type ConditionType uint
const (
CONDITION_AND ConditionType = iota
CONDITION_OR
)
type OrderType uint
const (
ORDERTYPE_ASC OrderType = iota
ORDERTYPE_DESC
)
type QueryFilter struct {
Condition ConditionType // AND , OR
Reversed bool // Reversed Field and Value if it is true
Field string
Operator string // Value will not used if empty.
Value interface{}
}
type QueryOrder struct {
Type OrderType
Field string
}
//type ConditionType uint
//
//const (
// CONDITION_AND ConditionType = iota
// CONDITION_OR
//)
//
//type OrderType uint
//
//const (
// ORDERTYPE_ASC OrderType = iota
// ORDERTYPE_DESC
//)
//
//type QueryFilter struct {
// Condition ConditionType // AND , OR
// Reversed bool // Reversed Field and Value if it is true
// Field string
// Operator string // Value will not used if empty.
// Value interface{}
//}
//
//type QueryOrder struct {
// Type OrderType
// Field string
//}

+ 0
- 243
models/types.go View File

@ -1,247 +1,4 @@
package models
import (
"errors"
"encoding/json"
"database/sql/driver"
"database/sql"
"regexp"
"strings"
"fmt"
)
type JASONDictionary map[string]interface{}
func (p *JASONDictionary) Scan(src interface{}) error {
if nil == src {
*p = nil
return nil
}
source, ok := src.([]byte)
if !ok {
return errors.New("Type assertion .([]byte) failed.")
}
var i JASONDictionary
err := json.Unmarshal(source, &i)
if err != nil {
return err
}
*p = i
return nil
}
func (p JASONDictionary) Value() (driver.Value, error) {
j, err := json.Marshal(p)
return j, err
}
type JSONDictionaryArray []JASONDictionary
func (p *JSONDictionaryArray) Scan(src interface{}) error {
source, ok := src.([]byte)
if !ok {
return errors.New("Type assertion .([]byte) failed.")
}
var i JSONDictionaryArray
err := json.Unmarshal(source, &i)
if err != nil {
return err
}
*p = i
return nil
}
func (p JSONDictionaryArray) Value() (driver.Value, error) {
j, err := json.Marshal(p)
return j, err
}
type StringArray []string
// PARSING ARRAYS
// SEE http://www.postgresql.org/docs/9.1/static/arrays.html#ARRAYS-IO
// Arrays are output within {} and a delimiter, which is a comma for most
// postgres types (; for box)
//
// Individual values are surrounded by quotes:
// The array output routine will put double quotes around element values if
// they are empty strings, contain curly braces, delimiter characters,
// double quotes, backslashes, or white space, or match the word NULL.
// Double quotes and backslashes embedded in element values will be
// backslash-escaped. For numeric data types it is safe to assume that double
// quotes will never appear, but for textual data types one should be prepared
// to cope with either the presence or absence of quotes.
// construct a regexp to extract values:
var (
// unquoted array values must not contain: (" , \ { } whitespace NULL)
// and must be at least one char
unquotedChar = `[^",\\{}\s(NULL)]`
unquotedValue = fmt.Sprintf("(%s)+", unquotedChar)
// quoted array values are surrounded by double quotes, can be any
// character except " or \, which must be backslash escaped:
quotedChar = `[^"\\]|\\"|\\\\`
quotedValue = fmt.Sprintf("\"(%s)*\"", quotedChar)
// an array value may be either quoted or unquoted:
arrayValue = fmt.Sprintf("(?P<value>(%s|%s))", unquotedValue, quotedValue)
// Array values are separated with a comma IF there is more than one value:
arrayExp = regexp.MustCompile(fmt.Sprintf("((%s)(,)?)", arrayValue))
valueIndex int
)
// Find the index of the 'value' named expression
func init() {
for i, subexp := range arrayExp.SubexpNames() {
if subexp == "value" {
valueIndex = i
break
}
}
}
// Parse the output string from the array type.
// Regex used: (((?P<value>(([^",\\{}\s(NULL)])+|"([^"\\]|\\"|\\\\)*")))(,)?)
func parseArray(array string) []string {
results := make([]string, 0)
matches := arrayExp.FindAllStringSubmatch(array, -1)
for _, match := range matches {
s := match[valueIndex]
// the string _might_ be wrapped in quotes, so trim them:
s = strings.Trim(s, "\"")
results = append(results, s)
}
return results
}
func (p *StringArray) Scan(src interface{}) error {
asBytes, ok := src.([]byte)
if !ok {
return error(errors.New("Scan source was not []bytes"))
}
asString := string(asBytes)
parsed := parseArray(asString)
(*p) = StringArray(parsed)
return nil
}
func (p StringArray) Value() (driver.Value, error) {
j, err := json.Marshal(p)
return j, err
}
type HSTOREDictionary map[string]interface{}
// escapes and quotes hstore keys/values
// s should be a sql.NullString or string
func hQuote(s interface{}) string {
var str string
switch v := s.(type) {
case sql.NullString:
if !v.Valid {
return "NULL"
}
str = v.String
case string:
str = v
default:
panic("not a string or sql.NullString")
}
str = strings.Replace(str, "\\", "\\\\", -1)
return `"` + strings.Replace(str, "\"", "\\\"", -1) + `"`
}
// Scan implements the Scanner interface.
//
// Note h.Map is reallocated before the scan to clear existing values. If the
// hstore column's database value is NULL, then h.Map is set to nil instead.
func (h *HSTOREDictionary) Scan(value interface{}) error {
if value == nil {
*h = nil
return nil
}
m := make(map[string]interface{})
var b byte
pair := [][]byte{{}, {}}
pi := 0
inQuote := false
didQuote := false
sawSlash := false
bindex := 0
for bindex, b = range value.([]byte) {
if sawSlash {
pair[pi] = append(pair[pi], b)
sawSlash = false
continue
}
switch b {
case '\\':
sawSlash = true
continue
case '"':
inQuote = !inQuote
if !didQuote {
didQuote = true
}
continue
default:
if !inQuote {
switch b {
case ' ', '\t', '\n', '\r':
continue
case '=':
continue
case '>':
pi = 1
didQuote = false
continue
case ',':
s := string(pair[1])
if !didQuote && len(s) == 4 && strings.ToLower(s) == "null" {
m[string(pair[0])] = nil // sql.NullString{String: "", Valid: false}
} else {
m[string(pair[0])] = string(pair[1]) // sql.NullString{String: string(pair[1]), Valid: true}
}
pair[0] = []byte{}
pair[1] = []byte{}
pi = 0
continue
}
}
}
pair[pi] = append(pair[pi], b)
}
if bindex > 0 {
s := string(pair[1])
if !didQuote && len(s) == 4 && strings.ToLower(s) == "null" {
m[string(pair[0])] = nil // sql.NullString{String: "", Valid: false}
} else {
m[string(pair[0])] = string(pair[1]) // sql.NullString{String: string(pair[1]), Valid: true}
}
}
*h = m
return nil
}
// Value implements the driver Valuer interface. Note if h.Map is nil, the
// database column value will be set to NULL.
func (h HSTOREDictionary) Value() (driver.Value, error) {
if h == nil {
return nil, nil
}
parts := []string{}
for key, val := range h {
thispart := hQuote(key) + "=>" + hQuote(val)
parts = append(parts, thispart)
}
return []byte(strings.Join(parts, ",")), nil
}

+ 1
- 0
xql/query.go View File

@ -0,0 +1 @@
package xql

+ 1
- 0
xql/session.go View File

@ -0,0 +1 @@
package xql

xql/dao.go → xql/table.go View File


+ 243
- 0
xql/types.go View File

@ -1,5 +1,15 @@
package xql
import (
"strings"
"fmt"
"regexp"
"database/sql"
"errors"
"encoding/json"
"database/sql/driver"
)
type ConditionType uint
const (
@ -28,5 +38,238 @@ type QueryOrder struct {
}
type JASONDictionary map[string]interface{}
func (p *JASONDictionary) Scan(src interface{}) error {
if nil == src {
*p = nil
return nil
}
source, ok := src.([]byte)
if !ok {
return errors.New("Type assertion .([]byte) failed.")
}
var i JASONDictionary
err := json.Unmarshal(source, &i)
if err != nil {
return err
}
*p = i
return nil
}
func (p JASONDictionary) Value() (driver.Value, error) {
j, err := json.Marshal(p)
return j, err
}
type JSONDictionaryArray []JASONDictionary
func (p *JSONDictionaryArray) Scan(src interface{}) error {
source, ok := src.([]byte)
if !ok {
return errors.New("Type assertion .([]byte) failed.")
}
var i JSONDictionaryArray
err := json.Unmarshal(source, &i)
if err != nil {
return err
}
*p = i
return nil
}
func (p JSONDictionaryArray) Value() (driver.Value, error) {
j, err := json.Marshal(p)
return j, err
}
type StringArray []string
// PARSING ARRAYS
// SEE http://www.postgresql.org/docs/9.1/static/arrays.html#ARRAYS-IO
// Arrays are output within {} and a delimiter, which is a comma for most
// postgres types (; for box)
//
// Individual values are surrounded by quotes:
// The array output routine will put double quotes around element values if
// they are empty strings, contain curly braces, delimiter characters,
// double quotes, backslashes, or white space, or match the word NULL.
// Double quotes and backslashes embedded in element values will be
// backslash-escaped. For numeric data types it is safe to assume that double
// quotes will never appear, but for textual data types one should be prepared
// to cope with either the presence or absence of quotes.
// construct a regexp to extract values:
var (
// unquoted array values must not contain: (" , \ { } whitespace NULL)
// and must be at least one char
unquotedChar = `[^",\\{}\s(NULL)]`
unquotedValue = fmt.Sprintf("(%s)+", unquotedChar)
// quoted array values are surrounded by double quotes, can be any
// character except " or \, which must be backslash escaped:
quotedChar = `[^"\\]|\\"|\\\\`
quotedValue = fmt.Sprintf("\"(%s)*\"", quotedChar)
// an array value may be either quoted or unquoted:
arrayValue = fmt.Sprintf("(?P<value>(%s|%s))", unquotedValue, quotedValue)
// Array values are separated with a comma IF there is more than one value:
arrayExp = regexp.MustCompile(fmt.Sprintf("((%s)(,)?)", arrayValue))
valueIndex int
)
// Find the index of the 'value' named expression
func init() {
for i, subexp := range arrayExp.SubexpNames() {
if subexp == "value" {
valueIndex = i
break
}
}
}
// Parse the output string from the array type.
// Regex used: (((?P<value>(([^",\\{}\s(NULL)])+|"([^"\\]|\\"|\\\\)*")))(,)?)
func parseArray(array string) []string {
results := make([]string, 0)
matches := arrayExp.FindAllStringSubmatch(array, -1)
for _, match := range matches {
s := match[valueIndex]
// the string _might_ be wrapped in quotes, so trim them:
s = strings.Trim(s, "\"")
results = append(results, s)
}
return results
}
func (p *StringArray) Scan(src interface{}) error {
asBytes, ok := src.([]byte)
if !ok {
return error(errors.New("Scan source was not []bytes"))
}
asString := string(asBytes)
parsed := parseArray(asString)
(*p) = StringArray(parsed)
return nil
}
func (p StringArray) Value() (driver.Value, error) {
j, err := json.Marshal(p)
return j, err
}
type HSTOREDictionary map[string]interface{}
// escapes and quotes hstore keys/values
// s should be a sql.NullString or string
func hQuote(s interface{}) string {
var str string
switch v := s.(type) {
case sql.NullString:
if !v.Valid {
return "NULL"
}
str = v.String
case string:
str = v
default:
panic("not a string or sql.NullString")
}
str = strings.Replace(str, "\\", "\\\\", -1)
return `"` + strings.Replace(str, "\"", "\\\"", -1) + `"`
}
// Scan implements the Scanner interface.
//
// Note h.Map is reallocated before the scan to clear existing values. If the
// hstore column's database value is NULL, then h.Map is set to nil instead.
func (h *HSTOREDictionary) Scan(value interface{}) error {
if value == nil {
*h = nil
return nil
}
m := make(map[string]interface{})
var b byte
pair := [][]byte{{}, {}}
pi := 0
inQuote := false
didQuote := false
sawSlash := false
bindex := 0
for bindex, b = range value.([]byte) {
if sawSlash {
pair[pi] = append(pair[pi], b)
sawSlash = false
continue
}
switch b {
case '\\':
sawSlash = true
continue
case '"':
inQuote = !inQuote
if !didQuote {
didQuote = true
}
continue
default:
if !inQuote {
switch b {
case ' ', '\t', '\n', '\r':
continue
case '=':
continue
case '>':
pi = 1
didQuote = false
continue
case ',':
s := string(pair[1])
if !didQuote && len(s) == 4 && strings.ToLower(s) == "null" {
m[string(pair[0])] = nil // sql.NullString{String: "", Valid: false}
} else {
m[string(pair[0])] = string(pair[1]) // sql.NullString{String: string(pair[1]), Valid: true}
}
pair[0] = []byte{}
pair[1] = []byte{}
pi = 0
continue
}
}
}
pair[pi] = append(pair[pi], b)
}
if bindex > 0 {
s := string(pair[1])
if !didQuote && len(s) == 4 && strings.ToLower(s) == "null" {
m[string(pair[0])] = nil // sql.NullString{String: "", Valid: false}
} else {
m[string(pair[0])] = string(pair[1]) // sql.NullString{String: string(pair[1]), Valid: true}
}
}
*h = m
return nil
}
// Value implements the driver Valuer interface. Note if h.Map is nil, the
// database column value will be set to NULL.
func (h HSTOREDictionary) Value() (driver.Value, error) {
if h == nil {
return nil, nil
}
parts := []string{}
for key, val := range h {
thispart := hQuote(key) + "=>" + hQuote(val)
parts = append(parts, thispart)
}
return []byte(strings.Join(parts, ",")), nil
}

Loading…
Cancel
Save