func (b *Backend) ExecQuery(statement FieldedExpression) ([]interface{}, apperror.Error) { translator := b.translator.New() if err := translator.PrepareExpression(statement); err != nil { return nil, err } if err := translator.Translate(statement); err != nil { return nil, err } sql := translator.String() args := translator.RawArguments() res := b.SqlExec(sql, args...) if res.Err() != nil { return nil, apperror.Wrap(res.Err(), "orient_error") } defer res.Close() var rawData interface{} if err := res.All(&rawData); err != nil { return nil, apperror.Wrap(err, "orient_result_retrieval_error") } rows, ok := rawData.([]orient.OIdentifiable) if !ok { return nil, apperror.New("invalid_non_record_orient_result") } items := make([]interface{}, len(rows), len(rows)) var info *db.ModelInfo if sel, ok := statement.(*SelectStmt); ok { info = b.ModelInfos().Find(sel.Collection()) } for i, rawItem := range rows { document, ok := rawItem.(*orient.Document) if !ok { continue } data := make(map[string]interface{}) if info != nil && info.PkAttribute() != nil { data[info.PkAttribute().Name()] = document.RId } for _, docEntry := range document.Fields() { data[docEntry.Name] = docEntry.Value } items[i] = data } return items, nil }
func (d *PostgresDialect) AfterCollectionCreate(info *db.ModelInfo) apperror.Error { for _, attr := range info.Attributes() { // Alter sequences to start at 1 instead of 0. if attr.AutoIncrement() { stmt := fmt.Sprintf("ALTER SEQUENCE %v_%v_seq RESTART WITH %v", info.BackendName(), attr.BackendName(), 1) if _, err := d.backend.SqlExec(stmt); err != nil { return apperror.Wrap(err, "sql_error") } } } return nil }
func (b *Backend) analyzeRelations(info *db.ModelInfo) apperror.Error { for _, field := range info.TransientFields() { relatedItem := reflect.New(field.StructType()) relatedInfo, err := b.InfoForModel(relatedItem) if err != nil { // No collection found, so assume a regular attribute. attr := db.BuildAttribute(field) info.AddAttribute(attr) continue } relation := db.BuildRelation(field) relation.SetModel(info) relation.SetRelatedModel(relatedInfo) if !relation.IsMany() { relation.SetRelationType(db.RELATION_TYPE_HAS_ONE) } else { relation.SetRelationType(db.RELATION_TYPE_HAS_MANY) } info.AddRelation(relation) } info.SetTransientFields(nil) return nil }
func (b *Backend) sort(info *db.ModelInfo, items *reflector.SliceReflector, field Expression, asc bool) apperror.Error { fieldName := "" if id, ok := field.(*IdentifierExpr); ok { fieldName = id.Identifier() } else if id, ok := field.(*ColFieldIdentifierExpr); ok { if id.Collection() != info.Collection() { return apperror.New("unsupported_sort", fmt.Sprint("The memory backend does not support sorting with joined collections")) } fieldName = id.Field() } else { return apperror.New("unsupported_sort", fmt.Sprintf("The memory backend does not support sorting with custom field expressions")) } attr := info.FindAttribute(fieldName) if attr == nil { return apperror.New("invalid_sort", fmt.Sprintf("Invalid sort for inexistant field %v", fieldName)) } if err := items.SortByField(attr.Name(), asc); err != nil { return apperror.Wrap(err, "sort_error") } return nil }
func (b *Backend) filterItem(info *db.ModelInfo, item *reflector.Reflector, filter Expression) (bool, apperror.Error) { switch f := filter.(type) { case *AndExpr: // Check each filter. for _, e := range f.Expressions() { flag, err := b.filterItem(info, item, e) if err != nil { return false, err } else if !flag { // One filter does not match, so return false. return false, nil } } // All filters matched, we can return true. return true, nil case *OrExpr: // Check each filter. for _, e := range f.Expressions() { flag, err := b.filterItem(info, item, e) if err != nil { return false, err } else if flag { // One match is enough, so return true. return true, nil } } // No filters matched, so return false. return false, nil case *NotExpr: // Reverse nested filter. flag, err := b.filterItem(info, item, f.Not()) if err != nil { return false, err } else { return !flag, nil } case FilterExpression: field := f.Field() fieldName := "" if id, ok := field.(*IdentifierExpr); ok { fieldName = id.Identifier() } else if id, ok := field.(*ColFieldIdentifierExpr); ok { if id.Collection() != info.Collection() { return false, apperror.New("unsupported_filter", fmt.Sprint("The memory backend does not support filtering with joined collections")) } fieldName = id.Field() } else { return false, apperror.New("unsupported_filter", fmt.Sprintf("The memory backend does not support filtering with custom field expressions")) } attr := info.FindAttribute(fieldName) if attr == nil { return false, apperror.New("invalid_filter", fmt.Sprintf("Invalid filter for inexistant field %v", fieldName)) } operator := f.Operator() var clauseValue interface{} if valExpr, ok := f.Clause().(*ValueExpr); ok { clauseValue = valExpr.Value() } else { return false, apperror.New("unsupported_filter_clause", fmt.Sprintf("The memory backend does not support filtering with custom clause expressions")) } if info.StructName() != "" { b.Logger().Infof("filtering item with %v %v %v", fieldName, operator, clauseValue) s, err := item.Struct() if err != nil { return false, apperror.Wrap(err, "invalid_model_error") } flag, err := s.Field(attr.Name()).CompareTo(clauseValue, operator) if err != nil { return false, apperror.Wrap(err, "compare_error") } return flag, nil } else { // Assume a map. if !item.IsMap() { return false, apperror.New("filter_invalid_model", "Could not filter because model value is neither struct nor map.") } flag, err := reflector.R(item.Value().MapIndex(reflect.ValueOf(attr.BackendName()))).CompareTo(clauseValue, operator) if err != nil { return false, apperror.Wrap(err, "compare_error") } return flag, nil } default: b.Logger().Panicf("Unhandled filter expression: %v", reflect.TypeOf(filter)) } return false, nil }