无法解析调用者sqlite3_bind:在Perl 6脚本中无法理解此错误

Jon*_*ein 5 sqlite perl6

脚本的目的:我希望能够使用它将费用插入到SQLite数据库中,然后再制作自定义报告以提取信息,这样我就可以更好地预算我的费用.

我根本不明白这个错误代码.

perl6 budgetpro.p6

苹果

一天一苹果,医生远离我

嗨,我很精干,很高兴见到你,Eggman

Cannot resolve caller sqlite3_bind(DBDish::SQLite::Native::STMT, Int,
Date); none of these signatures match:
    (DBDish::SQLite::Native::STMT $stmt, Int $n, Blob:D $b)
    (DBDish::SQLite::Native::STMT $stmt, Int $n, Real:D $d)
    (DBDish::SQLite::Native::STMT $stmt, Int $n, Int:D $i)
    (DBDish::SQLite::Native::STMT $stmt, Int $n, Any:U)
    (DBDish::SQLite::Native::STMT $stmt, Int $n, Str:D $d)   
    in method execute at /home/jon/opt/rakudo-star/share/perl6/site/sources/2D749062AA6D5641452CDA214FC7C566E7E3E2A1
(DBDish::SQLite::StatementHandle) line 38
    in method insert at budgetpro.p6 line 54   in block <unit> at budgetpro.p6 line 86`
Run Code Online (Sandbox Code Playgroud)
  2
  3 use v6;
  4 use DBIish;
  5
  6 constant DB = 'budgetpro.sqlite3';
  7 my $dbh = DBIish.connect('SQLite', database => DB);
  8
  9 #$dbh.do('drop table if exists Essential, Savings, Personal');
 10
 11 sub create-schema {
 12     $dbh.do(qq:to/SCHEMA/);
 13         create table if not exists Essential(
 14             id          integer primary key not null,
 15             name        varchar not null,
 16             quantity    integer not null,
 17             price       numeric(5,2) not null,
 18             description varchar not null,
 19             date        timestamp not null default (datetime('now'))
 20         );
 21         create table is not exists Savings(
 22             id          integer primary key not null,
 23             name        varchar not null,
 24             quantity    integer not null,
 25             price       numeric(5,2) not null,
 26             description varchar not null,
 27             date        timestamp not null default (datetime('now'))
 28         );
 29         create table if not exists Personal(
 30             id          integer primary key not null,
 31             name        varchar not null,
 32             quantity    integer not null,
 33             price       numeric(5,2) not null,
 34             description varchar not null,
 35             date        timestamp not null default (datetime('now'))
 36         );
 37     SCHEMA
 38 }
 39
 40 create-schema;
 41
 42 class Item {
 43     has $!table = 'Essential';
 44     has $.name;
 45     has $.quantity;
 46     has $.price;
 47     has $.description is rw;
 48     has $.timestamp;
 49     has Str $.notes is rw;
 50     method notes() { "$!notes\n" };
 51
 52     method insert($name, $quantity?, $price?, $description?, $timestamp?) {
 53         my $sth = $dbh.prepare("insert into Essential(name,quantity,price,description,date) values (?,?,?,?,?)");
 54         $sth.execute($name, $quantity, $price, $description, $timestamp);
 55
 56         say "Inserted $name, $quantity, $price, $description, $timestamp";
 57     }
 58 }
 59
 60 class Essential is Item {
 61     method greet($me: $person) {
 62         say "Hi, I am $me.^name(), nice to meet you, $person";
 63     }
 64 }
 65
 66 class Savings is Item {
 67 }
 68
 69 class Personal is Item {
 70 }
 71 
 72 my $food = Essential.new(
 73     name => 'Apple',
 74     price => .99,
 75     quantity => 2,
 76     notes => 'An apple a day keeps the doctor away'
 77 );
 78
 79 say $food.name;
 80 say $food.notes;
 81 Essential.new.greet('Eggman');
 82 say '';
 83
 84 my $test = Item.new();
 85
 86 $test.insert("Cheese", 2, 1.99, 'Block of cheddar', Date.new(now));
 87
 88 say $test.name;
Run Code Online (Sandbox Code Playgroud)

Bra*_*ert 7

问题是你打来电话:

$test.insert("Cheese", 2, 1.99, 'Block of cheddar', Date.new(now));
Run Code Online (Sandbox Code Playgroud)

最终会调用sqlite3_bind,但没有候选者接受Date第三个参数的实例.


它会接受的一个实例Blob,Int,Real(Numeric但不是Complex),或Str.它也会接受一个未定义的值(Any:U).

在我看来,它是数据库驱动程序中的一个错误或缺少的功能,它不接受DateTime或甚至可能是一个Instant对象,并自动将其转换为SQLite期望的内容.


我还想指出有Date.todayDateTime.now.后者将跟踪当前时区信息,而DateTime.new(now)不会.
(这是故意的,因为没有办法知道它Instant来自哪里.)


jjm*_*elo 6

@Brad Gilbert是对的.语句只允许5种数据结构,而且都不是Date.TIME并且DATE是SQL中的标准数据类型,但目前它们似乎没有DBIish支持.在这种情况下,您只需将第85行更改为

$test.insert("Cheese", 2, 1.99, 'Block of cheddar', Date.new(now).Str);
Run Code Online (Sandbox Code Playgroud)

让你的程序处理日期转换,你也必须改变Essential表的定义.您还可以让数据库处理默认值.你必须消除"not null",因为它与default句子冲突.

还有一些小错误.这个,减少到最小表达式,工作并将默认时间戳正确插入数据库(通过使用sqlite3命令行检查):

use v6;
use DBIish;

constant DB = 'budgetpro.sqlite3';
my $dbh = DBIish.connect('SQLite', database => DB);

#$dbh.do('drop table if exists Essential, Savings, Personal');

sub create-schema {
    $dbh.do(qq:to/SCHEMA/);
        create table if not exists Essential(
            id          integer primary key not null,
            name        varchar not null,
            quantity    integer not null,
            price       numeric(5,2) not null,
            description varchar not null,
            date        timestamp default (datetime('now'))
        );
    SCHEMA
}

create-schema;

class Item {
    has $!table = 'Essential';
    has $.name;
    has $.quantity;
    has $.price;
    has $.description is rw;
    has $.timestamp;
    has Str $.notes is rw;
    method notes() { "$!notes\n" };

    method insert($name, $quantity?, $price?, $description?, $timestamp?) {
        my $sth = $dbh.prepare("insert into Essential(name,quantity,price,description) values (?,?,?,?)");
        $sth.execute($name, $quantity, $price, $description);

        say "Inserted $name, $quantity, $price, $description";
    }
}

Item.new().insert("Cheese", 2, 1.99, 'Block of cheddar');
Run Code Online (Sandbox Code Playgroud)

请注意,您的Item类实际上并不是通过运行insert句子来实例化的,因此$test.name在最后一行中只返回一个空对象,其默认值分配给实例变量.您可能要改变insert的方法来实例化项的子方法它插入到数据库中.