On Wednesday, September 4, 2013 11:49:39 AM UTC-7, GregD wrote:

> Jeremy-
>
> Updated gist:
> https://gist.github.com/6240781.git
>
> Down to 2 failing tests.  Not sure how to fix these 2.
>

First, let me say that that is very impressive.  Only 7 pending tests is 
very good, some of the adapters that ship with Sequel have more pending 
tests than that.
 

>
>
> Failures:
>
>   1) RcteTree Plugin should not populate :children associations for final 
> level when loading descendants to a given level
>      Failure/Error: nodes[0].associations[:children].map{|c1| 
> c1.associations[:children]}.should == [nil, nil]
>        expected: [nil, nil]
>             got: [[], []] (using ==)
>        Diff:
>        @@ -1,2 +1,2 @@
>        -[nil, nil]
>        +[[], []]
>      # ./spec/integration/plugin_test.rb:858:in `block (2 levels) in <top 
> (required)>'
>
> I don't even know where to begin to figure out what is going on with this. 
>  Very complicated recursion sql is generated and looks valid (works in 
> dbisql).  Something to do with the eager method, maybe? Although all the 
> other tests with eager are working.
>

You might want to add some debugging code to the `if level` block near line 
297 of the plugin.  It should be setting no_cache to true for the 
grandchildren, but if for some reason the dataset is returning a level 
value that is not equal to 1, it will be false, so the associations hash in 
the grandchildren will be initialized to [] in line 307.  You could try 
changing `obj.values.delete(la)` to `obj.values.delete(la).to_i` on line 
297 and see if that fixes it.
 

>   2) Database foreign key parsing should parse foreign key information 
> into an array of hashes
>      Failure/Error: @db.alter_table(:b){drop_foreign_key :e}
>      Sequel::DatabaseError:
>        Sequel::SqlAnywhere::SQLAnywhereException: Foreign key name 'A' not 
> found
>      # ./lib/sequel/database/misc.rb:402:in `raise_error'
>      # ./lib/sequel/adapters/sqlanywhere.rb:97:in `block in execute_dui'
>      # ./lib/sequel/database/connecting.rb:229:in `block in synchronize'
>      # ./lib/sequel/connection_pool/threaded.rb:104:in `hold'
>      # ./lib/sequel/database/connecting.rb:229:in `synchronize'
>      # ./lib/sequel/adapters/sqlanywhere.rb:91:in `execute_dui'
>      # ./lib/sequel/database/query.rb:43:in `execute_ddl'
>      # ./lib/sequel/database/schema_methods.rb:377:in `block in 
> apply_alter_table'
>      # ./lib/sequel/database/schema_methods.rb:377:in `each'
>      # ./lib/sequel/database/schema_methods.rb:377:in `apply_alter_table'
>      # ./lib/sequel/database/schema_methods.rb:382:in 
> `apply_alter_table_generator'
>      # ./lib/sequel/extensions/constraint_validations.rb:283:in 
> `apply_alter_table_generator'
>      # ./lib/sequel/database/schema_methods.rb:78:in `alter_table'
>      # ./spec/integration/schema_test.rb:227:in `block (2 levels) in <top 
> (required)>'
>
> This one is 2 fold:
> 1) SqlAnywhere will not allow you to add or drop a column or a foreign key 
> if if violates a uniqueness constraint.  So, before adding/dropping I query 
> the schema to see if I need to do something i.e. alter the column to not be 
> null if it is going to be a foreign key in another table.  So, I made 
> the appropriate alter_table_sql to do so to get these tests to work.  In 
> doing so, I cause the above to happen because this statement:
>    
>    @db.alter_table(:b){drop_foreign_key :e}
>
> generates 2 identical ALTER TABLE statements in the operations list of:
>
> ALTER TABLE B DROP FOREIGN KEY A 
> ALTER TABLE B DROP FOREIGN KEY A
>
> Both are valid. The problem is the second will fail because of the first 
> one removed the fk.  I can add uniq to the return value of Sequel method 
> alter_table_sql_list and it will work, but don't like that.  If I remove 
> the code that is generating the first ALTER TABLE, then I get a different 
> test that fails which is dropping of a column that is used as a fk.  Code 
> that is generating the first ALTER TABLE:
>
>           when :drop_column
>             sqls = []
>             f_keys = foreign_key_list(table)
>             constraint_names = f_keys.map{|h| h[:name] if 
> h[:columns].include?(op[:name])}
>             constraint_names.each do |constraint|
>               sqls << alter_table_sql(table, {:op => :drop_constraint, 
> :type => :foreign_key, :name => constraint})   <---------- right here.
>             end
>             sqls << "ALTER TABLE #{quote_schema_table(table)} DROP 
> #{column_definition_sql(op)}"
>

I can think of two ways to handle this:

1) In the code that generates the first DROP FOREIGN KEY, find a way to 
determine if it would meet the conditions such that the second DROP FOREIGN 
KEY would be used, and don't add the first DROP FOREIGN KEY in that case.

2) Always have the first DROP FOREIGN KEY used, but dup and modify the op 
to add a flag that the second DROP FOREIGN KEY code would check and not add 
the DROP FOREIGN KEY in that case.

Of the two options, 1) might be easier.  If someone calls drop_foreign_key 
with a single symbol, you know you have to drop the column, and if your 
drop column code already uses DROP FOREIGN KEY in that case, you probably 
don't need to add it.


>
> 2) I had to comment out this part of the test because I can not figure out 
> what I need to do to prevent the constraint violation that it is causing.   
> I think I have to add a uniqueness index for the composite key and I still 
> can't figure out the ALTER TABLE SQL for that and have been trying the 
> SqlAnyhere Sybase Central client program.  Hopefully, I can figure that one 
> out here soon.
>
> ~line 220 of schema_test.rb
>     #@db.alter_table(:a){add_index [:d, :c], :unique=>true}
>     #@db.alter_table(:b){add_foreign_key [:f, :e], :a, :key=>[:d, :c]}
>     #@pr[:b, [[:e], :a, [:pk, :c]], [[:f], :a, [:c]], [[:f], :a, [:d]], 
> [[:f, :e], :a, [:d, :c]]]
>
>     #@db.alter_table(:b){drop_foreign_key [:f, :e]}
>     @pr[:b, [[:e], :a, [:pk, :c]], [[:f], :a, [:c]], [[:f], :a, [:d]]]
>

If that add_index is failing, I'm not sure why, unless unique composite 
indexes must be specified differently on SQLAnywhere.
 

> The pending ones are with reasons:
> Pending:
>   Sequel::Database should provide ability to check connections for validity
>     # Not yet working on sqlanywhere
>     # ./spec/integration/spec_helper.rb:75
>
> It looks like the sqlanywhere native gem acts just like the sybase client 
> software dbisql and sybase central where if you disconnect and then issue 
> an SQL statement it auto reconnects you to your last connection sending 
> back the results.
>

Yuck.  Is there no way to turn that off?  That's a pretty horrible idea. 
 Think starting a transaction and having a disconnect happen midway 
through.  With transparent auto reconnection, Sequel thinks you are inside 
a transaction, but SQLAnwhere is outside a transaction.  That's not a good 
situation to be in.
 

>
>   Simple dataset operations with nasty table names should work correctly
>     # Not yet working on sqlanywhere
>     # ./spec/integration/spec_helper.rb:75
>

Expected.
 

>  Sequel::Database should correctly escape multiple backslash strings
>     # Not yet working on sqlanywhere
>     # ./spec/integration/spec_helper.rb:75
>

Unless there is a good reason for this failing, I would look at it more 
carefully.  This sounds like it could lead to SQL injection.  I'm just 
guessing that from the spec description, as I can't find this spec 
description in the current integration tests.
 

>   Sequel::Database should properly escape identifiers
>     # Not yet working on sqlanywhere
>     # ./spec/integration/spec_helper.rb:75
>

Expected.
 

>   Sequel::Dataset DSL support should work with bitwise shift operators
>     # Not yet working on sqlanywhere
>     # ./spec/integration/spec_helper.rb:75
>

Is there no way to emulate bitwise shifts on SQLAnywhere?  Usually they can 
be emulated with simple multiple or divide of power(2, arg).
 

>   Bound Argument Types should handle blob type with embedded zeros
>     # Not yet working on sqlanywhere
>     # ./spec/integration/spec_helper.rb:75
>

Is there a way to hex-encode the blobs to allow this?
 

>   Supported types should support generic file type
>     # Not yet working on sqlanywhere
>     # ./spec/integration/spec_helper.rb:75
>

Probably related to above issue.
 

> All of these have to do with escaping characters and the native 
> sqlanywhere gem use of StringValueCStr and there is no other method to call 
> that does not use that on the sql string that is passed in.  I split the 
> escape backslash strings into 2 tests.  On that worked for sqlanywhere and 
> the ones that did not putting them into a cspecify.  I called it escape 
> multiple backslash strings.
>

Ah, that's why I couldn't find it.  Anyway, you might want to take another 
look and convince yourself 100% that SQL injection is not possible in that 
case.
 

> I can set up a JDBC sqlanyhere adapter.  That should not take too long to 
> do and see if these can pass.
>

That would be great.
 
I would definitely like to get this merged into Sequel when you have 
finished.  Ideally I would have a local SQLAnywhere installation in a VM 
that I could use for testing (to make sure future Sequel versions don't 
break SQLAnywhere support).  If that's something you could walk me through, 
I would appreciate it.  However, even if there are things preventing me 
from testing it locally, I still think it would be beneficial to merge it.

Thank you very much for your continued determination in getting the 
sqlanywhere adapter in shape.

Thanks,
Jeremy

-- 
You received this message because you are subscribed to the Google Groups 
"sequel-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sequel-talk.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to