Tencent / wcdb

WCDB is a cross-platform database framework developed by WeChat.
Other
10.84k stars 1.41k forks source link

winq syntax #1168

Closed 0x1306a94 closed 2 months ago

0x1306a94 commented 2 months ago

The language of WCDB

Swift

The version of WCDB

2.1.6

The platform of WCDB

iOS

The installation of WCDB

Carthage

What's the issue?

Is it possible to support writing similar to NSCompoundPredicate? I used the following extension, and the generated sql should be illegal. I checked the test code of the Swift part in the repository, but couldn't find how to write this.

extension Collection where Element: ExpressionConvertible {
    func and() -> ExpressionConvertible {
        if self.isEmpty {
            return Expression(nilLiteral: ())
        }

        let sql = self.map { $0.asExpression().description }
            .joined(separator: " AND ")

        return Expression(stringLiteral: "(\(sql))")
    }

    func or() -> ExpressionConvertible {
        if self.isEmpty {
            return Expression(nilLiteral: ())
        }

        let sql = self.map { $0.asExpression().description }
            .joined(separator: " OR ")

        return Expression(stringLiteral: "(\(sql))")
    }
}

func test() {
    let conditions = [
        Order.Properties.orderId.in(table: "order") == Ticket.Properties.orderId.in(table: "ticket"),
        Ticket.Properties.ticketCode.in(table: "ticket") == "xxxx",
        Ticket.Properties.orderId.in(table: "ticket") == BindParameter(1),
    ]

    print("and: \(conditions.and().asExpression().description)")
    // and: '(order.orderId == ticket.orderId AND ticket.ticketCode == ''xxxx'' AND ticket.orderId == ?1)'
    print("or: \(conditions.or().asExpression().description)")
    // or: '(order.orderId == ticket.orderId OR ticket.ticketCode == ''xxxx'' OR ticket.orderId == ?1)'
}

For example, some dynamic conditions are very cumbersome to write using the following method

func test(orderId: String, ticketCode: String?) {
    var condition = Ticket.Properties.orderId == orderId
    if let ticketCode, !ticketCode.isEmpty {
        condition = condition && Ticket.Properties.ticketCode == ticketCode
    }

    print("sql: \(condition.description)")
}
Qiuwen-chen commented 2 months ago

Winq does not support raw string expression

0x1306a94 commented 2 months ago

@Qiuwen-chen Can subsequent versions consider supporting NSCompoundPredicate?

Qiuwen-chen commented 2 months ago

@Qiuwen-chen Can subsequent versions consider supporting NSCompoundPredicate?

NO

0x1306a94 commented 2 months ago

@Qiuwen-chen I mean support for NSCompoundPredicate-like syntax. For example, you can convert a list into a set of AND or OR

func test(orderId: String, ticketCode: String?) {
    var condition = Ticket.Properties.orderId == orderId
    var dynamicConditions: [ExpressionConvertible] = []
    if let ticketCode, !ticketCode.isEmpty {
        dynamicConditions.append(Ticket.Properties.ticketCode == ticketCode)
        dynamicConditions.append(Ticket.Properties.telephone == "dddd")
    }

    let finalCondition = condition && dynamicConditions.and()
    // sql: (orderId = 'dd' AND (ticketCode = 'xx' AND telephone = 'ddd'))

    // let finalCondition = condition && dynamicConditions.or()
    // sql: (orderId = 'dd' AND (ticketCode = 'xx' OR telephone = 'ddd'))

    print("sql: \(condition.description)")
}

func testPlaceholder(orderId: String?, ticketCode: String?) {
    var condition = WCDBSwift.Condition.Placeholder // sql:
    if let orderId, let ticketCode {
        condition =  condition && Ticket.Properties.orderId == orderId &&
        Ticket.Properties.ticketCode == ticketCode
        // sql: (orderId = 'xx' AND ticketCode = 'xx')
    }
}
Qiuwen-chen commented 2 months ago

@Qiuwen-chen I mean support for NSCompoundPredicate-like syntax. For example, you can convert a list into a set of AND or OR

func test(orderId: String, ticketCode: String?) {
    var condition = Ticket.Properties.orderId == orderId
    var dynamicConditions: [ExpressionConvertible] = []
    if let ticketCode, !ticketCode.isEmpty {
        dynamicConditions.append(Ticket.Properties.ticketCode == ticketCode)
        dynamicConditions.append(Ticket.Properties.telephone == "dddd")
    }

    let finalCondition = condition && dynamicConditions.and()
    // sql: (orderId = 'dd' AND (ticketCode = 'xx' AND telephone = 'ddd'))

    // let finalCondition = condition && dynamicConditions.or()
    // sql: (orderId = 'dd' AND (ticketCode = 'xx' OR telephone = 'ddd'))

    print("sql: \(condition.description)")
}

func testPlaceholder(orderId: String?, ticketCode: String?) {
    var condition = WCDBSwift.Condition.Placeholder // sql:
    if let orderId, let ticketCode {
        condition =  condition && Ticket.Properties.orderId == orderId &&
        Ticket.Properties.ticketCode == ticketCode
        // sql: (orderId = 'xx' AND ticketCode = 'xx')
    }
}

It seems that you can do it outside of wcdb

0x1306a94 commented 2 months ago

@Qiuwen-chen It just doesn't work? That's why it needs support in wcdb! Although this can be achieved through the following extension, Expression(nilLiteral: ()) will output NULL and Expression(stringLiteral: "") will output ''

extension Collection where Element: ExpressionConvertible {
    func and() -> ExpressionConvertible {
        if self.isEmpty {
            return Expression(nilLiteral: ())
        }

        let finalExpression = self.reduce(Expression(nilLiteral: ())) { $0 && $ 1 }        
        return finalExpression
    }

    func or() -> ExpressionConvertible {
        if self.isEmpty {
            return Expression(nilLiteral: ())
        }

        let finalExpression = self.reduce(Expression(nilLiteral: ())) { $0 || $ 1 }        
        return finalExpression
    }
}
Qiuwen-chen commented 2 months ago

You need a empty expression, may be you can try Expression(booleanLiteral: true)

0x1306a94 commented 2 months ago

@Qiuwen-chen

Qiuwen-chen commented 2 months ago

Yes, WCDB C++ can be fully used on the OHOS platform. NSCompoundPredicate-like syntax is not a normal sql expression, I don't want to support this officially.