mysql_query_rules defined in proxysql.cnf but not loaded - proxysql
My proxysql.cnf contains:
# ...
mysql_query_rules:
(
{
active = 1
match_digest = "^SHOW.*"
destination_hostgroup = 3
apply = 0
},
{
active = 1
match_digest = "^SELECT.*"
destination_hostgroup = 3
apply = 0
},
{
active = 1
match_digest = "^SELECT.* FOR UPDATE"
destination_hostgroup = 2
apply = 1
},
)
# ...
But when proxysql starts, the mysql_query_rules defintion is not loaded.
select * from mysql_query_rules;
Empty set (0.001 sec)
How to make proxysql loads the mysql_query_rules definition from the proxysql.cnf file at startup?
The rule_id field is mandatory.
{
rule_id=1
active = 1
match_digest = "^SHOW.*"
destination_hostgroup = 3
apply = 0
},
Related
Error with the message "Cannot cast (inet::physicallayer::Ieee80211DimensionalTransmission*) to type 'const inet::physicallayer::IScalarSignal *'"
I use Omnet++ and Inet 4.4, I want to simulate a scenario to investigate the effect of interference, which is as follows: In a network consisting of two pairs of nodes including a node called source and a node called destination, in which node source sends packets to node destination and is tuned in channel 2 of Ieee802.11b/g, let's examine the second pair consisting of node Node1 and node Node2, which node Node1 sends packets to node Node 4 and is tuned in channel 4. But recently a problem appear very often and the simulations are stopped, the error is this: check_and_cast(): Cannot cast (inet::physicallayer::Ieee80211DimensionalTransmission*) to type 'const inet::physicallayer::IScalarSignal *' -- in module (inet::physicallayer::Ieee80211Radio) AnalogModelShowcaseDistanceNetworkRM.source.wlan[1].radio (id=200), at t=0.001s, event #24 My omnetpp.ini is as: [Config Distance] network = AnalogModelShowcaseDistanceNetworkRM sim-time-limit = 5s # Maryam **.radio.packetErrorRate.result-recording-modes = +vector # Maryam **.radio.bitErrorRate.result-recording-modes = +vector # application parameters *.source.numApps = 1 *.source.app[0].typename = "UdpBasicApp" *.source.app[*].destAddresses = "destination" *.source.app[*].destPort = 1000 *.source.app[*].messageLength = 1000byte *.source.app[*].sendInterval = 1ms *.destination.numApps = 1 *.destination.app[0].typename = "UdpSink" *.destination.app[*].localPort = 1000 *.Node1.numApps = 1 *.Node1.app[0].typename = "UdpBasicApp" *.Node1.app[*].destAddresses = "Node2" *.Node1.app[*].destPort = 1001 *.Node1.app[*].messageLength = 1000byte *.Node1.app[*].sendInterval = 1ms *.Node2.numApps = 1 *.Node2.app[0].typename = "UdpSink" *.Node2.app[*].localPort = 1001 *.source.numWlanInterfaces = 2 *.destination.numWlanInterfaces = 2 *.Node1.numWlanInterfaces = 2 *.Node2.numWlanInterfaces = 2 *.source.wlan[*].radio.typename = "Ieee80211DimensionalRadio" *.destination.wlan[*].radio.typename = "Ieee80211DimensionalRadio" *.Node*.wlan[*].radio.typename = "Ieee80211DimensionalRadio" *.source.wlan[*].radio.centerFrequency = 2.412GHz *.source.wlan[*].radio.bandwidth = 2MHz *.source.wlan[*].radio.transmitter.power = 2mW *.source.wlan[*].radio.transmitter.bitrate = 2Mbps *.source.wlan[*].radio.transmitter.preambleDuration = 0s *.source.wlan[*].radio.transmitter.headerLength = 96b *.source.wlan[*].radio.transmitter.modulation = "BPSK" *.source.wlan[*].radio.receiver.sensitivity = -85dBm *.source.wlan[*].radio.receiver.energyDetection = -85dBm *.source.wlan[*].radio.receiver.snirThreshold = 4dB *.destination.wlan[*].radio.centerFrequency = 2.412GHz *.destination.wlan[*].radio.bandwidth = 2MHz *.destination.wlan[*].radio.transmitter.power = 2mW *.destination.wlan[*].radio.transmitter.bitrate = 2Mbps *.destination.wlan[*].radio.transmitter.preambleDuration = 0s *.destination.wlan[*].radio.transmitter.headerLength = 96b *.destination.wlan[*].radio.transmitter.modulation = "BPSK" *.destination.wlan[*].radio.receiver.sensitivity = -85dBm *.destination.wlan[*].radio.receiver.energyDetection = -85dBm *.destination.wlan[*].radio.receiver.snirThreshold = 4dB *.Node*.wlan[*].radio.centerFrequency = 2.412GHz *.Node*.wlan[*].radio.bandwidth = 2MHz *.Node*.wlan[*].radio.transmitter.power = 2mW *.Node*.wlan[*].radio.transmitter.bitrate = 2Mbps *.Node*.wlan[*].radio.transmitter.preambleDuration = 0s *.Node*.wlan[*].radio.transmitter.headerLength = 96b *.Node*.wlan[*].radio.transmitter.modulation = "BPSK" *.Node*.wlan[*].radio.receiver.sensitivity = -85dBm *.Node*.wlan[*].radio.receiver.energyDetection = -85dBm *.Node*.wlan[*].radio.receiver.snirThreshold = 4dB *.source.wlan[0].radio.channelNumber = 2 *.destination.wlan[0].radio.channelNumber = 2 *.Node1.wlan[0].radio.channelNumber = 4 *.Node2.wlan[0].radio.channelNumber = 4 # mobility parameters *.destination.mobility.typename = "LinearMobility" *.destination.mobility.initialMovementHeading = 0deg *.destination.mobility.speed = 200mps *.destination.mobility.constraintAreaMinX = 500m *.destination.mobility.constraintAreaMaxX = 1200m # wlan *.source.**.transmitter.power = 12mW *.source.**.displayCommunicationRange = true **.backgroundNoise.power = -105dBm **.wlan*.mac.*.rateSelection.dataFrameBitrate = 54Mbps **.wlan*.mac.dcf.channelAccess.pendingQueue.packetCapacity = 14 # visualizer parameters *.visualizer.*.numStatisticVisualizers = 2 *.visualizer.*.statisticVisualizer[0].signalName = "packetSentToUpper" *.visualizer.*.statisticVisualizer[0].statisticExpression = "packetErrorRate" *.visualizer.*.statisticVisualizer[0].sourceFilter = "*.destination.wlan[*].radio" *.visualizer.*.statisticVisualizer[0].format = "packetErrorRate(Maryam): %v" *.visualizer.*.statisticVisualizer[1].signalName = "packetSentToUpper" *.visualizer.*.statisticVisualizer[1].statisticExpression = "minimumSnir" *.visualizer.*.statisticVisualizer[1].sourceFilter = "*.destination.wlan[*].radio" *.visualizer.*.statisticVisualizer[1].format = "SNIR(Maryam): %v" *.visualizer.*.statisticVisualizer[1].placementHint = "topLeft" *.visualizer.*.dataLinkVisualizer[0].displayLinks = true *.visualizer.*.packetDropVisualizer[0].displayPacketDrops = true *.visualizer.*.packetDropVisualizer[0].nodeFilter = "destination" *.visualizer.*.packetDropVisualizer[0].labelFormat = "(Maryam) %r" *.visualizer.*.infoVisualizer[0].displayInfos = true *.visualizer.*.infoVisualizer[0].modules = "*.destination.app[0]" How do I solve this?
You need to set the radioMedium type to dimensional as well radioMedium: Ieee80211DimensionalRadioMedium { parameters: #display("p=62.247997,287.14398"); } In the NED file.
Table keys not sorting correctly
I have a table that looks like this { ["slot1"] = {} ["slot2"] = {} ["slot3"] = {} ["slot4"] = {} ["slot5"] = {} ["slot6"] = {} } When I do a for k, v in pairs loop I want the keys to go from slot1- the last slot. At the moment when I do a loop the order is inconsistent, slot 5 comes first etc. What is the best way to do this? also I did not design this table, and I cannot change how the keys look
You can write a simple custom iterator: local tbl = { ["slot1"] = {}, ["slot2"] = {}, ["slot3"] = {}, ["slot4"] = {}, ["slot5"] = {}, ["slot6"] = {} } function slots(tbl) local i = 0 return function() i = i + 1 if tbl["slot" .. i] ~= nil then return i, tbl["slot" .. i] end end end for i, element in slots(tbl) do print(i, element) end Output: 1 table: 0xd575f0 2 table: 0xd57720 3 table: 0xd57760 4 table: 0xd5aa40 5 table: 0xd5aa80 6 table: 0xd5aac0
Create a new table: slot = {} for k,v in pairs(original_table) do local i=tonumber(k:match("%d+$")) slot[i]=v end
Lua table orders are undeterministic. see here what makes lua tables key order be undeterministic For your table you can try this local t = { ["slot1"] = {}, ["slot2"] = {}, ["slot3"] = {}, ["slot4"] = {}, ["slot5"] = {}, ["slot6"] = {} } local slotNumber = 1 while(t['slot' .. slotNumber]) do slot = t['slot' .. slotNumber] -- do stuff with slot slotNumber = slotNumber + 1 end This method does not handle if the table skips a slot number.
How can I interpolate a random octet into a CIDR block in Terraform?
I have the following random_test.tf Terraform file, which I've successfully initialized: resource "random_integer" "octet" { min = 0 max = 255 } variable "base_cidr_block" { description = "Class A CIDR block in RFC 1918 range" default = "10.0.0.0/8" } provider "null" { base_cidr_block = "10.${random_integer.octet.result}.0.0/16" } output "ip_block" { value = var.base_cidr_block } I'm using the null provider as a placeholder to test defining a 10.0.0.0/16 CIDR block with a random second octet. However, base_cidr_block is always 10.0.0.0/8 even though I'm expecting it to be assigned something like 10.100.0.0/16, which would then be shown on standard output as ip_block. Instead, I always get the default: $ terraform plan An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # random_integer.octet will be created + resource "random_integer" "octet" { + id = (known after apply) + max = 255 + min = 0 + result = (known after apply) } Plan: 1 to add, 0 to change, 0 to destroy. Changes to Outputs: + ip_block = "10.0.0.0/8" Running terraform apply then always sends ip_block = "10.0.0.0/8" to the console. What am I doing wrong?
Here's what I've come up with, although I may not understand the intent. First, I've created a module. I'm using the random_integer, and setting a keeper: variable "netname" { default = "default" } variable "subnet" { default = "10.0.0.0/8" } resource "random_integer" "octet" { min = 0 max = 255 keepers = { netname = var.netname } } output "rand" { value = random_integer.octet.result } output "random-subnet" { value = "${cidrsubnet("${var.subnet}", 8, random_integer.octet.result)}" } Next I call the module, passing in my keeper, and optionally the subnet: module "get-subnet-1" { source = "./module/" netname = "subnet-1" } output "get-subnet-1" { value = module.get-subnet-1.random-subnet } module "get-subnet-2" { source = "./module/" netname = "subnet-2" } output "get-subnet-2" { value = module.get-subnet-2.random-subnet } Finally, my output: Apply complete! Resources: 1 added, 0 changed, 0 destroyed. Outputs: get-subnet-1 = 10.2.0.0/16 get-subnet-2 = 10.6.0.0/16
Hibernate, Oracle, Play: Unable to build EntityManagerFactory error
I'm getting a really vague exception from Hibernate when trying to use it with Oracle.(it works normally with MySQL) I have the following configuration: Play Framework: 2.3.7 ojdbc14.jar Hibernate: 4.3.8.Final I'm using Oracle 10i The application manages to connect, but fails when trying to build the Entity Manager. I tried to build it manually, but I got the same error when using Play's annotation #play.db.jpa.Transactional For example: Accessing via raw JDBC works normally. My database settings in application.conf: db.default.driver=oracle.jdbc.driver.OracleDriver db.default.url="jdbc:oracle:thin:#IP:1521:SID" db.default.user=USER_NAME db.default.pass=ROOT db.default.jndiName=DefaultDS jpa.default=defaultPersistenceUnit My Persistence.xml: <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0"> <persistence-unit name="defaultPersistenceUnit" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <non-jta-data-source>DefaultDS</non-jta-data-source> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" /> </properties> </persistence-unit> </persistence> Here's the exception: play.api.UnexpectedException: Unexpected exception[PersistenceException: Unable to build entity manager factory] at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(ApplicationProvider.scala:166) ~[play_2.11-2.3.7.jar:2.3.7] at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(ApplicationProvider.scala:130) ~[play_2.11-2.3.7.jar:2.3.7] at scala.Option.map(Option.scala:145) ~[scala-library-2.11.1.jar:na] at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1.apply(ApplicationProvider.scala:130) ~[play_2.11-2.3.7.jar:2.3.7] at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1.apply(App licationProvider.scala:128) ~[play_2.11-2.3.7.jar:2.3.7] Caused by: javax.persistence.PersistenceException: Unable to build entity manager factory at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:83) ~[hibernate-entitymanager-4.3.8.Final.jar:4.3.8.Final] at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:54) ~[hibernate-entitymanager-4.3.8.Final.jar:4.3.8.Final] at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55) ~[hibernate-jpa-2.1-api-1.0.0.Final.jar:1.0.0.Final] at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39) ~[hibernate-jpa-2.1-api-1.0.0.Final.jar:1.0.0.Final] at play.db.jpa.JPAPlugin.onStart(JPAPlugin.java:38) ~[play-java-jpa_2.11-2.3.7.jar:2.3.7] Caused by: java.lang.NullPointerException: null at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:244) ~[hibernate-core-4.3.8.Final.jar:4.3.8.Final] at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:111) ~[hibernate-core-4.3.8.Final.jar:4.3.8.Final] at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:234) ~[hibernate-core-4.3.8.Final.jar:4.3.8.Final] at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:206) ~[hibernate-core-4.3.8.Final.jar:4.3.8.Final] at org.hibernate.cfg.Configuration.buildTypeRegistrations(Configuration.java:1887) ~[hibernate-core-4.3.8.Final.jar:4.3.8.Final] ///////////////////////////////////////////// UPDATED: The properties that hibernate receives are: 0 = {HashMap$Node#10729} "gopherProxySet" -> "false" 1 = {HashMap$Node#10730} "awt.toolkit" -> "sun.lwawt.macosx.LWCToolkit" 2 = {HashMap$Node#10731} "file.encoding.pkg" -> "sun.io" 3 = {HashMap$Node#10732} "java.specification.version" -> "1.8" 4 = {HashMap$Node#10733} "sun.cpu.isalist" -> 5 = {HashMap$Node#10734} "sun.jnu.encoding" -> "UTF-8" 6 = {HashMap$Node#10735} "hibernate.dialect" -> "org.hibernate.dialect.Oracle10gDialect" 7 = {HashMap$Node#10736} "java.class.path" -> "/Users/rodrigoarantes1/Library/Application Support/IntelliJIdea14/Scala/launcher/sbt-launch.jar:/Applications/IntelliJ IDEA 14.app/Contents/lib/idea_rt.jar" 8 = {HashMap$Node#10737} "java.naming.provider.url" -> "/" 9 = {HashMap$Node#10738} "sbt.global.base" -> "/private/var/folders/8l/k806t46d2fl5sq2rt6gzp7z00000gp/T/sbt-global-plugin1stub" 10 = {HashMap$Node#10739} "java.vm.vendor" -> "Oracle Corporation" 11 = {HashMap$Node#10740} "sun.arch.data.model" -> "64" 12 = {HashMap$Node#10741} "jline.shutdownhook" -> "false" 13 = {HashMap$Node#10742} "java.vendor.url" -> "http://java.oracle.com/" 15 = {HashMap$Node#10744} "javax.persistence.jdbc.user" -> "USERNAME" 16 = {HashMap$Node#10745} "hibernate.transaction.factory_class" -> "class org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory" 17 = {HashMap$Node#10746} "javax.persistence.jdbc.url" -> "jdbc:oracle:thin:#127.0.0.1:1521:XE" 18 = {HashMap$Node#10747} "jline.terminal" -> "none" 19 = {HashMap$Node#10748} "os.name" -> "Mac OS X" 20 = {HashMap$Node#10749} "java.vm.specification.version" -> "1.8" 21 = {HashMap$Node#10750} "sun.java.launcher" -> "SUN_STANDARD" 23 = {HashMap$Node#10752} "sun.boot.library.path" -> "/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/jre/lib" 24 = {HashMap$Node#10753} "sun.java.command" -> "xsbt.boot.Boot run" 25 = {HashMap$Node#10754} "http.nonProxyHosts" -> "local|*.local|169.254/16|*.169.254/16" 26 = {HashMap$Node#10755} "sun.cpu.endian" -> "little" 27 = {HashMap$Node#10756} "user.home" -> "/Users/rodrigoarantes1" 28 = {HashMap$Node#10757} "user.language" -> "en" 29 = {HashMap$Node#10758} "java.specification.vendor" -> "Oracle Corporation" 30 = {HashMap$Node#10759} "java.home" -> "/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/jre" 31 = {HashMap$Node#10760} "file.separator" -> "/" 32 = {HashMap$Node#10761} "line.separator" -> "\n" 33 = {HashMap$Node#10762} "java.vm.specification.vendor" -> "Oracle Corporation" 34 = {HashMap$Node#10763} "java.specification.name" -> "Java Platform API Specification" 35 = {HashMap$Node#10764} "java.awt.graphicsenv" -> "sun.awt.CGraphicsEnvironment" 36 = {HashMap$Node#10765} "javax.persistence.jdbc.driver" -> "oracle.jdbc.driver.OracleDriver" 37 = {HashMap$Node#10766} "sun.boot.class.path" -> "/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/jre/lib/sunrsasign.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/jre/classes" 38 = {HashMap$Node#10767} "jline.esc.timeout" -> "0" 39 = {HashMap$Node#10768} "sun.management.compiler" -> "HotSpot 64-Bit Tiered Compilers" 40 = {HashMap$Node#10769} "ftp.nonProxyHosts" -> "local|*.local|169.254/16|*.169.254/16" 41 = {HashMap$Node#10770} "java.runtime.version" -> "1.8.0_45-b14" 42 = {HashMap$Node#10771} "java.naming.factory.initial" -> "tyrex.naming.MemoryContextFactory" 43 = {HashMap$Node#10772} "user.name" -> "rodrigoarantes1" 44 = {HashMap$Node#10773} "path.separator" -> ":" 45 = {HashMap$Node#10774} "os.version" -> "10.10.4" 46 = {HashMap$Node#10775} "java.endorsed.dirs" -> "/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/jre/lib/endorsed" 47 = {HashMap$Node#10776} "java.runtime.name" -> "Java(TM) SE Runtime Environment" 48 = {HashMap$Node#10777} "sbt.log.noformat" -> "true" 49 = {HashMap$Node#10778} "hibernate.ejb.persistenceUnitName" -> "oraclePersistenceUnit" 50 = {HashMap$Node#10779} "file.encoding" -> "UTF8" 51 = {HashMap$Node#10780} "sun.nio.ch.bugLevel" -> 52 = {HashMap$Node#10781} "java.vm.name" -> "Java HotSpot(TM) 64-Bit Server VM" 53 = {HashMap$Node#10782} "java.vendor.url.bug" -> "http://bugreport.sun.com/bugreport/" 54 = {HashMap$Node#10783} "java.io.tmpdir" -> "/var/folders/8l/k806t46d2fl5sq2rt6gzp7z00000gp/T/" 55 = {HashMap$Node#10784} "java.version" -> "1.8.0_45" 57 = {HashMap$Node#10786} "os.arch" -> "x86_64" 58 = {HashMap$Node#10787} "java.vm.specification.name" -> "Java Virtual Machine Specification" 59 = {HashMap$Node#10788} "java.awt.printerjob" -> "sun.lwawt.macosx.CPrinterJob" 60 = {HashMap$Node#10789} "sun.os.patch.level" -> "unknown" 61 = {HashMap$Node#10790} "java.library.path" -> ":/Library/Oracle/instantclient_11_2:/Users/rodrigoarantes1/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.:/Users/rodrigoarantes1/SourceTree-Repos/Project/target/native_libraries/64bits" 62 = {HashMap$Node#10791} "java.vendor" -> "Oracle Corporation" 63 = {HashMap$Node#10792} "java.vm.info" -> "mixed mode" 64 = {HashMap$Node#10793} "java.vm.version" -> "25.45-b02" 65 = {HashMap$Node#10794} "hibernate.bytecode.use_reflection_optimizer" -> "false" 66 = {HashMap$Node#10795} "hibernate.connection.datasource" -> "OracleDS" 67 = {HashMap$Node#10796} "sun.io.unicode.encoding" -> "UnicodeBig" 68 = {HashMap$Node#10797} "java.ext.dirs" -> "/Users/rodrigoarantes1/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java" 69 = {HashMap$Node#10798} "javax.persistence.jdbc.password" -> "ROOT" 70 = {HashMap$Node#10799} "java.class.version" -> "52.0" 71 = {HashMap$Node#10800} "socksNonProxyHosts" -> "local|*.local|169.254/16|*.169.254/16" More Details: The metadata generated by hibernate is: connection = {OracleConnection#10996} url = {String#10997} "jdbc:oracle:thin:#127.0.0.1:1521:XE" user = {String#10998} "USER_NAME" password = {String#10999} "ROOT" database = {String#11000} "127.0.0.1:1521:XE" auto_commit = true protocol = {String#11001} "thin" db_access = {TTC7Protocol#11002} conversion = {TTCConversion#11003} lob_dbaccess = null XA_wants_error = false UsingXA = false m_txn_mode = 0 fdo = null big_endian = null statement_table = {Hashtable#11004} size = 0 closed = false m_clientIdSet = false m_clientId = null default_batch = 1 default_row_prefetch = 10 report_remarks = false include_synonyms = false restrict_getTables = false m_accumulateBatchResult = true m_j2ee13Compliant = false m_v8compatible = false looseTimestampDateCheck = false dataSizeScale = 1 noCachingBuffer = false trans_level = 2 map = null m_javaObjectMap = {Hashtable#11005} size = 0 descriptorCache = {Hashtable#11006} size = 0 statement_holding_line = null m_dbMetaData = {OracleDatabaseMetaData#10994} connection = {OracleConnection#10996} url = {String#10997} "jdbc:oracle:thin:#127.0.0.1:1521:XE" user = {String#10998} "USER_NAME" password = {String#10999} "ROOT" database = {String#11000} "127.0.0.1:1521:XE" auto_commit = true protocol = {String#11001} "thin" db_access = {TTC7Protocol#11002} conversion = {TTCConversion#11003} lob_dbaccess = null XA_wants_error = false UsingXA = false m_txn_mode = 0 fdo = null big_endian = null statement_table = {Hashtable#11004} size = 0 closed = false m_clientIdSet = false m_clientId = null default_batch = 1 default_row_prefetch = 10 report_remarks = false include_synonyms = false restrict_getTables = false m_accumulateBatchResult = true m_j2ee13Compliant = false m_v8compatible = false looseTimestampDateCheck = false dataSizeScale = 1 noCachingBuffer = false trans_level = 2 map = null m_javaObjectMap = {Hashtable#11005} size = 0 descriptorCache = {Hashtable#11006} size = 0 statement_holding_line = null m_dbMetaData = {OracleDatabaseMetaData#10994} connection = {OracleConnection#10996} url = {String#10997} "jdbc:oracle:thin:#127.0.0.1:1521:XE" user = {String#10998} "USER_NAME" password = {String#10999} "ROOT" database = {String#11000} "127.0.0.1:1521:XE" auto_commit = true protocol = {String#11001} "thin" db_access = {TTC7Protocol#11002} conversion = {TTCConversion#11003} lob_dbaccess = null XA_wants_error = false UsingXA = false m_txn_mode = 0 fdo = null big_endian = null statement_table = {Hashtable#11004} size = 0 closed = false m_clientIdSet = false m_clientId = null default_batch = 1 default_row_prefetch = 10 report_remarks = false include_synonyms = false restrict_getTables = false m_accumulateBatchResult = true m_j2ee13Compliant = false m_v8compatible = false looseTimestampDateCheck = false dataSizeScale = 1 noCachingBuffer = false trans_level = 2 map = null m_javaObjectMap = {Hashtable#11005} size = 0 descriptorCache = {Hashtable#11006} size = 0 statement_holding_line = null m_dbMetaData = {OracleDatabaseMetaData#10994} physicalStatus = true logicalHandle = false m_opc = null m_opc_oc = null m_osql = {OracleSql#11007} m_warning = null m_readOnly = false m_startTime = 0 statementCache = null m_stmtClearMetaData = false m_process_escapes = true m_defaultAutoRefetch = true m_occ = null m_privData = null defaultFixedString = false m_svptStmt = null wrapper = null connectionProperties = {Properties#11008} size = 3 timeout = null m_clientData = null m_sessionTimeZone = null m_dbTzCalendar = null procedureResultUnknown = 0 procedureNoResult = 1 procedureReturnsResult = 2 procedureColumnUnknown = 0 procedureColumnIn = 1 procedureColumnInOut = 2 procedureColumnOut = 4 procedureColumnReturn = 5 procedureColumnResult = 3 procedureNoNulls = 0 procedureNullable = 1 procedureNullableUnknown = 2 columnNoNulls = 0 columnNullable = 1 columnNullableUnknown = 2 versionColumnUnknown = 0 versionColumnNotPseudo = 1 versionColumnPseudo = 2 importedKeyCascade = 0 importedKeyRestrict = 1 importedKeySetNull = 2 typeNoNulls = 0 typeNullable = 1 typeNullableUnknown = 2 typePredNone = 0 typePredChar = 1 typePredBasic = 2 typeSearchable = 3 tableIndexStatistic = 0 tableIndexClustered = 1 tableIndexHashed = 2 tableIndexOther = 3 attributeNoNulls = 0 attributeNullable = 1 attributeNullableUnknown = 2 sqlStateXOpen = 1 sqlStateSQL99 = 2 physicalStatus = true logicalHandle = false m_opc = null m_opc_oc = null m_osql = {OracleSql#11007} isV8Compatible = false current_argument = 1 parameterCount = 0 i = 26 length = 26 c = 'E' 69 first = false in_string = false odbc_sql = {String#11009} "SET TRANSACTION READ WRITE" oracle_sql = {StringBuffer#11010} "SET TRANSACTION READ WRITE" token_buffer = {StringBuffer#11011} "" isLocate = false m_warning = null m_readOnly = false m_startTime = 0 statementCache = null m_stmtClearMetaData = false m_process_escapes = true m_defaultAutoRefetch = true m_occ = null m_privData = null defaultFixedString = false m_svptStmt = null wrapper = null connectionProperties = {Properties#11008} size = 3 0 = {Hashtable$Entry#11018} "user" -> "USER_NAME" 1 = {Hashtable$Entry#11019} "dll" -> "ocijdbc9" 2 = {Hashtable$Entry#11020} "protocol" -> "thin" timeout = null m_clientData = null m_sessionTimeZone = null m_dbTzCalendar = null procedureResultUnknown = 0 procedureNoResult = 1 procedureReturnsResult = 2 procedureColumnUnknown = 0 procedureColumnIn = 1 procedureColumnInOut = 2 procedureColumnOut = 4 procedureColumnReturn = 5 procedureColumnResult = 3 procedureNoNulls = 0 procedureNullable = 1 procedureNullableUnknown = 2 columnNoNulls = 0 columnNullable = 1 columnNullableUnknown = 2 versionColumnUnknown = 0 versionColumnNotPseudo = 1 versionColumnPseudo = 2 importedKeyCascade = 0 importedKeyRestrict = 1 importedKeySetNull = 2 typeNoNulls = 0 typeNullable = 1 typeNullableUnknown = 2 typePredNone = 0 typePredChar = 1 typePredBasic = 2 typeSearchable = 3 tableIndexStatistic = 0 tableIndexClustered = 1 tableIndexHashed = 2 tableIndexOther = 3 attributeNoNulls = 0 attributeNullable = 1 attributeNullableUnknown = 2 sqlStateXOpen = 1 sqlStateSQL99 = 2 physicalStatus = true logicalHandle = false m_opc = null m_opc_oc = null m_osql = {OracleSql#11007} isV8Compatible = false current_argument = 1 parameterCount = 0 i = 26 length = 26 c = 'E' 69 first = false in_string = false odbc_sql = {String#11009} "SET TRANSACTION READ WRITE" oracle_sql = {StringBuffer#11010} "SET TRANSACTION READ WRITE" token_buffer = {StringBuffer#11011} "" isLocate = false m_warning = null m_readOnly = false m_startTime = 0 statementCache = null m_stmtClearMetaData = false m_process_escapes = true m_defaultAutoRefetch = true m_occ = null m_privData = null defaultFixedString = false m_svptStmt = null wrapper = null connectionProperties = {Properties#11008} size = 3 timeout = null m_clientData = null m_sessionTimeZone = null m_dbTzCalendar = null procedureResultUnknown = 0 procedureNoResult = 1 procedureReturnsResult = 2 procedureColumnUnknown = 0 procedureColumnIn = 1 procedureColumnInOut = 2 procedureColumnOut = 4 procedureColumnReturn = 5 procedureColumnResult = 3 procedureNoNulls = 0 procedureNullable = 1 procedureNullableUnknown = 2 columnNoNulls = 0 columnNullable = 1 columnNullableUnknown = 2 versionColumnUnknown = 0 versionColumnNotPseudo = 1 versionColumnPseudo = 2 importedKeyCascade = 0 importedKeyRestrict = 1 importedKeySetNull = 2 typeNoNulls = 0 typeNullable = 1 typeNullableUnknown = 2 typePredNone = 0 typePredChar = 1 typePredBasic = 2 typeSearchable = 3 tableIndexStatistic = 0 tableIndexClustered = 1 tableIndexHashed = 2 tableIndexOther = 3 attributeNoNulls = 0 attributeNullable = 1 attributeNullableUnknown = 2 sqlStateXOpen = 1 sqlStateSQL99 = 2 The Exception being thrown by Hibernate: File: JdbcServicesImpl.java Method: meta.supportsNamedParameters(); SQLState = null vendorCode = 17023 next = null detailMessage = {String#13599} "Unsupported feature" cause = {SQLException#13595} "java.sql.SQLException: Unsupported feature" stackTrace = {StackTraceElement[0]#13600} suppressedExceptions = {Collections$UnmodifiableRandomAccessList#13601} size = 0 Could someone help me figuring out what the problem might be and how to solve it? Any help is really appreciated. Thank you
Since I havent used play, my answer is not a copy and paste but it will show you the way how to do it. It seems that you are missing a lot of properties in your persistence unit. You are not providing required fields such as username, password, url schema etc. Please have a look at: https://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/configuration.html An example for hsqldb is from the docs above: <persistence> <persistence-unit name="manager1" transaction-type="RESOURCE_LOCAL"> <class>org.hibernate.ejb.test.Cat</class> <class>org.hibernate.ejb.test.Distributor</class> <class>org.hibernate.ejb.test.Item</class> <properties> <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/> <property name="javax.persistence.jdbc.user" value="sa"/> <property name="javax.persistence.jdbc.password" value=""/> <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:."/> <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/ <property name="hibernate.max_fetch_depth" value="3"/> <!-- cache configuration --> <property name="hibernate.ejb.classcache.org.hibernate.ejb.test.Item" value="read-write"/> <property name="hibernate.ejb.collectioncache.org.hibernate.ejb.test.Item.distributors" value="read-write, RegionName"/> <!-- alternatively to <class> and <property> declarations, you can use a regular hibernate.cfg.xml file --> <!-- property name="hibernate.ejb.cfgfile" value="/org/hibernate/ejb/test/hibernate.cfg.xml"/ --> </properties> </persistence-unit> </persistence>
The issue was related to the Oracle driver. My original configuration works fine with the driver ojdbc7.jar So my play/jpa configuration remained as: application.conf db.default.driver=oracle.jdbc.driver.OracleDriver db.default.url="jdbc:oracle:thin:#IP:1521:SID" db.default.user=USER_NAME db.default.pass=ROOT db.default.jndiName=DefaultDS jpa.default=defaultPersistenceUnit persistence.xml <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0"> <persistence-unit name="defaultPersistenceUnit" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <non-jta-data-source>DefaultDS</non-jta-data-source> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" /> </properties> </persistence-unit> </persistence> I hope it helps someone EDITED: I also tried with ojdbc14.jar because I needed to connect o an oracle 8i server. You only need to add the following property to your persistence.xml <property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/> Thanks
How do you do dynamic / dependent drop downs in Google Sheets?
How do you get a sub-category column to populate a drop down based on the value selected in the main category drop down in google sheets? I googled around and couldn't find any good solutions, therefore I wanted to share my own. Please see my answer below.
You can start with a google sheet set up with a main page and drop down source page like shown below. You can set up the first column drop down through the normal Data > Validations menu prompts. Main Page Drop Down Source Page After that, you need to set up a script with the name onEdit. (If you don't use that name, the getActiveRange() will do nothing but return cell A1) And use the code provided here: function onEdit() { var ss = SpreadsheetApp.getActiveSpreadsheet(); var sheet = SpreadsheetApp.getActiveSheet(); var myRange = SpreadsheetApp.getActiveRange(); var dvSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Categories"); var option = new Array(); var startCol = 0; if(sheet.getName() == "Front Page" && myRange.getColumn() == 1 && myRange.getRow() > 1){ if(myRange.getValue() == "Category 1"){ startCol = 1; } else if(myRange.getValue() == "Category 2"){ startCol = 2; } else if(myRange.getValue() == "Category 3"){ startCol = 3; } else if(myRange.getValue() == "Category 4"){ startCol = 4; } else { startCol = 10 } if(startCol > 0 && startCol < 10){ option = dvSheet.getSheetValues(3,startCol,10,1); var dv = SpreadsheetApp.newDataValidation(); dv.setAllowInvalid(false); //dv.setHelpText("Some help text here"); dv.requireValueInList(option, true); sheet.getRange(myRange.getRow(),myRange.getColumn() + 1).setDataValidation(dv.build()); } if(startCol == 10){ sheet.getRange(myRange.getRow(),myRange.getColumn() + 1).clearDataValidations(); } } } After that, set up a trigger in the script editor screen by going to Edit > Current Project Triggers. This will bring up a window to have you select various drop downs to eventually end up at this: You should be good to go after that!
Caution! The scripts have a limit: it handles up to 500 values in a single drop-down list. Multi-line, multi-Level, multi-List, multi-Edit-Line Dependent Drop-Down Lists in Google Sheets. Script More Info Article Video Last version of the script on GitHub This solution is not perfect, but it gives some benefits: Let you make multiple dropdown lists Gives more control Source Data is placed on the only sheet, so it's simple to edit First of all, here's working example, so you can test it before going further. Installation: Prepare Data Make the first list as usual: Data > Validation Add Script, set some variables Done! Prepare Data Data looks like a single table with all possible variants inside it. It must be located on a separate sheet, so it can be used by the script. Look at this example: Here we have four levels, each value repeats. Note that 2 columns on the right of data are reserved, so don't type/paste there any data. First simple Data Validation (DV) Prepare a list of unique values. In our example, it is a list of Planets. Find free space on sheet with data, and paste formula: =unique(A:A) On your mainsheet select first column, where DV will start. Go to Data > Validation and select range with a unique list. Script Paste this code into script editor: function onEdit(event) { // Change Settings: //-------------------------------------------------------------------------------------- var TargetSheet = 'Main'; // name of sheet with data validation var LogSheet = 'Data1'; // name of sheet with data var NumOfLevels = 4; // number of levels of data validation var lcol = 2; // number of column where validation starts; A = 1, B = 2, etc. var lrow = 2; // number of row where validation starts var offsets = [1,1,1,2]; // offsets for levels // ^ means offset column #4 on one position right. // ===================================================================================== SmartDataValidation(event, TargetSheet, LogSheet, NumOfLevels, lcol, lrow, offsets); // Change Settings: //-------------------------------------------------------------------------------------- var TargetSheet = 'Main'; // name of sheet with data validation var LogSheet = 'Data2'; // name of sheet with data var NumOfLevels = 7; // number of levels of data validation var lcol = 9; // number of column where validation starts; A = 1, B = 2, etc. var lrow = 2; // number of row where validation starts var offsets = [1,1,1,1,1,1,1]; // offsets for levels // ===================================================================================== SmartDataValidation(event, TargetSheet, LogSheet, NumOfLevels, lcol, lrow, offsets); } function SmartDataValidation(event, TargetSheet, LogSheet, NumOfLevels, lcol, lrow, offsets) { //-------------------------------------------------------------------------------------- // The event handler, adds data validation for the input parameters //-------------------------------------------------------------------------------------- var FormulaSplitter = ';'; // depends on regional setting, ';' or ',' works for US //-------------------------------------------------------------------------------------- // =================================== key variables ================================= // // ss sheet we change (TargetSheet) // br range to change // scol number of column to edit // srow number of row to edit // CurrentLevel level of drop-down, which we change // HeadLevel main level // r current cell, which was changed by user // X number of levels could be checked on the right // // ls Data sheet (LogSheet) // // ====================================================================================== // Checks var ts = event.source.getActiveSheet(); var sname = ts.getName(); if (sname !== TargetSheet) { return -1; } // not main sheet // Test if range fits var br = event.range; var scol = br.getColumn(); // the column number in which the change is made var srow = br.getRow() // line number in which the change is made var ColNum = br.getWidth(); if ((scol + ColNum - 1) < lcol) { return -2; } // columns... if (srow < lrow) { return -3; } // rows // Test range is in levels var columnsLevels = getColumnsOffset_(offsets, lcol); // Columns for all levels var CurrentLevel = getCurrentLevel_(ColNum, br, scol, columnsLevels); if(CurrentLevel === 1) { return -4; } // out of data validations if(CurrentLevel > NumOfLevels) { return -5; } // last level /* ts - sheet with validation, sname = name of sheet NumOfLevels = 4 offsets = [1,1,1,2] - last offset is 2 because need to skip 1 column columnsLevels = [4,5,6,8] - Columns of validation Columns 7 is skipped | 1 2 3 4 5 6 7 8 9 |----+----+----+----+----+----+----+----+----+ 1 | | | | | | | x | | | |----+----+----+----+----+----+----+----+----+ 2 | | | | v | V | ? | x | ? | | lrow = 2 - number of row where validation starts |----+----+----+----+----+----+----+----+----+ 3 | | | | | | | x | | | |----+----+----+----+----+----+----+----+----+ 4 | | | | | | | x | | | |----+----+----+----+----+----+----+----+----+ | | | | | | | | | Currentlevel = 3 - the number of level to change | | | | | | | br - cell, user changes: scol - column, srow - row, | | ColNum = 1 - width |__|________ _.....____| | v | Drop-down lists | | lcol = 4 - number of column where validation starts */ // Constants var ReplaceCommas = getDecimalMarkIsCommaLocals(); // // ReplaceCommas = true if locale uses commas to separate decimals var ls = SpreadsheetApp.getActive().getSheetByName(LogSheet); // Data sheet var RowNum = br.getHeight(); /* Adjust the range 'br' ??? ! xxx x xxx x xxx => x xxx x xxx x */ br = ts.getRange(br.getRow(), columnsLevels[CurrentLevel - 2], RowNum); // Levels var HeadLevel = CurrentLevel - 1; // main level var X = NumOfLevels - CurrentLevel + 1; // number of levels left // determine columns on the sheet "Data" var KudaCol = NumOfLevels + 2; var KudaNado = ls.getRange(1, KudaCol); // 1 place for a formula var lastRow = ls.getLastRow(); var ChtoNado = ls.getRange(1, KudaCol, lastRow, KudaCol); // the range with list, returned by a formula // ============================================================================= > loop > var CurrLevelBase = CurrentLevel; // remember the first current level for (var j = 1; j <= RowNum; j++) // [01] loop rows start { // refresh first val var currentRow = br.getCell(j, 1).getRow(); loopColumns_(HeadLevel, X, currentRow, NumOfLevels, CurrLevelBase, lastRow, FormulaSplitter, CurrLevelBase, columnsLevels, br, KudaNado, ChtoNado, ReplaceCommas, ts); } // [01] loop rows end } function getColumnsOffset_(offsets, lefColumn) { // Columns for all levels var columnsLevels = []; var totalOffset = 0; for (var i = 0, l = offsets.length; i < l; i++) { totalOffset += offsets[i]; columnsLevels.push(totalOffset + lefColumn - 1); } return columnsLevels; } function test_getCurrentLevel() { var br = SpreadsheetApp.getActive().getActiveSheet().getRange('A5:C5'); var scol = 1; /* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | range |xxxxx| dv range |xxxxxxxxxxxxxxxxx| levels 1 2 3 level 2 */ Logger.log(getCurrentLevel_(1, br, scol, [1,2,3])); // 2 /* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | range |xxxxxxxxxxx| dv range |xxxxx| |xxxxx| |xxxxx| levels 1 2 3 level 2 */ Logger.log(getCurrentLevel_(2, br, scol, [1,3,5])); // 2 /* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | range |xxxxxxxxxxxxxxxxx| dv range |xxxxx| |xxxxxxxxxxx| levels 1 2 3 level 2 */ Logger.log(getCurrentLevel_(3, br, scol, [1,5,6])); // 2 /* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | range |xxxxxxxxxxxxxxxxx| dv range |xxxxxxxxxxx| |xxxxx| levels 1 2 3 level 3 */ Logger.log(getCurrentLevel_(3, br, scol, [1,2,8])); // 3 /* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | range |xxxxxxxxxxxxxxxxx| dv range |xxxxxxxxxxxxxxxxx| levels 1 2 3 level 4 (error) */ Logger.log(getCurrentLevel_(3, br, scol, [1,2,3])); /* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | range |xxxxxxxxxxxxxxxxx| dv range |xxxxxxxxxxxxxxxxx| levels level 1 (error) */ Logger.log(getCurrentLevel_(3, br, scol, [5,6,7])); // 1 } function getCurrentLevel_(ColNum, br, scol, columnsLevels) { var colPlus = 2; // const if (ColNum === 1) { return columnsLevels.indexOf(scol) + colPlus; } var CurrentLevel = -1; var level = 0; var column = 0; for (var i = 0; i < ColNum; i++ ) { column = br.offset(0, i).getColumn(); level = columnsLevels.indexOf(column) + colPlus; if (level > CurrentLevel) { CurrentLevel = level; } } return CurrentLevel; } function loopColumns_(HeadLevel, X, currentRow, NumOfLevels, CurrentLevel, lastRow, FormulaSplitter, CurrLevelBase, columnsLevels, br, KudaNado, ChtoNado, ReplaceCommas, ts) { for (var k = 1; k <= X; k++) { HeadLevel = HeadLevel + k - 1; CurrentLevel = CurrLevelBase + k - 1; var r = ts.getRange(currentRow, columnsLevels[CurrentLevel - 2]); var SearchText = r.getValue(); // searched text X = loopColumn_(X, SearchText, HeadLevel, HeadLevel, currentRow, NumOfLevels, CurrentLevel, lastRow, FormulaSplitter, CurrLevelBase, columnsLevels, br, KudaNado, ChtoNado, ReplaceCommas, ts); } } function loopColumn_(X, SearchText, HeadLevel, HeadLevel, currentRow, NumOfLevels, CurrentLevel, lastRow, FormulaSplitter, CurrLevelBase, columnsLevels, br, KudaNado, ChtoNado, ReplaceCommas, ts) { // if nothing is chosen! if (SearchText === '') // condition value ='' { // kill extra data validation if there were // columns on the right if (CurrentLevel <= NumOfLevels) { for (var f = 0; f < X; f++) { var cell = ts.getRange(currentRow, columnsLevels[CurrentLevel + f - 1]); // clean & get rid of validation cell.clear({contentsOnly: true}); cell.clear({validationsOnly: true}); // exit columns loop } } return 0; // end loop this row } // formula for values var formula = getDVListFormula_(CurrentLevel, currentRow, columnsLevels, lastRow, ReplaceCommas, FormulaSplitter, ts); KudaNado.setFormula(formula); // get response var Response = getResponse_(ChtoNado, lastRow, ReplaceCommas); var Variants = Response.length; // build data validation rule if (Variants === 0.0) // empty is found { return; } if(Variants >= 1.0) // if some variants were found { var cell = ts.getRange(currentRow, columnsLevels[CurrentLevel - 1]); var rule = SpreadsheetApp .newDataValidation() .requireValueInList(Response, true) .setAllowInvalid(false) .build(); // set validation rule cell.setDataValidation(rule); } if (Variants === 1.0) // // set the only value { cell.setValue(Response[0]); SearchText = null; Response = null; return X; // continue doing DV } // the only value return 0; // end DV in this row } function getDVListFormula_(CurrentLevel, currentRow, columnsLevels, lastRow, ReplaceCommas, FormulaSplitter, ts) { var checkVals = []; var Offs = CurrentLevel - 2; var values = []; // get values and display values for a formula for (var s = 0; s <= Offs; s++) { var checkR = ts.getRange(currentRow, columnsLevels[s]); values.push(checkR.getValue()); } var LookCol = colName(CurrentLevel-1); // gets column name "A,B,C..." var formula = '=unique(filter(' + LookCol + '2:' + LookCol + lastRow; // =unique(filter(A2:A84 var mathOpPlusVal = ''; var value = ''; // loop levels for multiple conditions for (var i = 0; i < CurrentLevel - 1; i++) { formula += FormulaSplitter; // =unique(filter(A2:A84; LookCol = colName(i); value = values[i]; mathOpPlusVal = getValueAndMathOpForFunction_(value, FormulaSplitter, ReplaceCommas); // =unique(filter(A2:A84;B2:B84="Text" if ( Array.isArray(mathOpPlusVal) ) { formula += mathOpPlusVal[0]; formula += LookCol + '2:' + LookCol + lastRow; // =unique(filter(A2:A84;ROUND(B2:B84 formula += mathOpPlusVal[1]; } else { formula += LookCol + '2:' + LookCol + lastRow; // =unique(filter(A2:A84;B2:B84 formula += mathOpPlusVal; } } formula += "))"; //=unique(filter(A2:A84;B2:B84="Text")) return formula; } function getValueAndMathOpForFunction_(value, FormulaSplitter, ReplaceCommas) { var result = ''; var splinter = ''; var type = typeof value; // strings if (type === 'string') return '="' + value + '"'; // date if(value instanceof Date) { return ['ROUND(', FormulaSplitter +'5)=ROUND(DATE(' + value.getFullYear() + FormulaSplitter + (value.getMonth() + 1) + FormulaSplitter + value.getDate() + ')' + '+' + 'TIME(' + value.getHours() + FormulaSplitter + value.getMinutes() + FormulaSplitter + value.getSeconds() + ')' + FormulaSplitter + '5)']; } // numbers if (type === 'number') { if (ReplaceCommas) { return '+0=' + value.toString().replace('.', ','); } else { return '+0=' + value; } } // booleans if (type === 'boolean') { return '=' + value; } // other return '=' + value; } function getResponse_(allRange, l, ReplaceCommas) { var data = allRange.getValues(); var data_ = allRange.getDisplayValues(); var response = []; var val = ''; for (var i = 0; i < l; i++) { val = data[i][0]; if (val !== '') { var type = typeof val; if (type === 'boolean' || val instanceof Date) val = String(data_[i][0]); if (type === 'number' && ReplaceCommas) val = val.toString().replace('.', ',') response.push(val); } } return response; } function colName(n) { var ordA = 'a'.charCodeAt(0); var ordZ = 'z'.charCodeAt(0); var len = ordZ - ordA + 1; var s = ""; while(n >= 0) { s = String.fromCharCode(n % len + ordA) + s; n = Math.floor(n / len) - 1; } return s; } function getDecimalMarkIsCommaLocals() { // list of Locals Decimal mark = comma var LANGUAGE_BY_LOCALE = { af_NA: "Afrikaans (Namibia)", af_ZA: "Afrikaans (South Africa)", af: "Afrikaans", sq_AL: "Albanian (Albania)", sq: "Albanian", ar_DZ: "Arabic (Algeria)", ar_BH: "Arabic (Bahrain)", ar_EG: "Arabic (Egypt)", ar_IQ: "Arabic (Iraq)", ar_JO: "Arabic (Jordan)", ar_KW: "Arabic (Kuwait)", ar_LB: "Arabic (Lebanon)", ar_LY: "Arabic (Libya)", ar_MA: "Arabic (Morocco)", ar_OM: "Arabic (Oman)", ar_QA: "Arabic (Qatar)", ar_SA: "Arabic (Saudi Arabia)", ar_SD: "Arabic (Sudan)", ar_SY: "Arabic (Syria)", ar_TN: "Arabic (Tunisia)", ar_AE: "Arabic (United Arab Emirates)", ar_YE: "Arabic (Yemen)", ar: "Arabic", hy_AM: "Armenian (Armenia)", hy: "Armenian", eu_ES: "Basque (Spain)", eu: "Basque", be_BY: "Belarusian (Belarus)", be: "Belarusian", bg_BG: "Bulgarian (Bulgaria)", bg: "Bulgarian", ca_ES: "Catalan (Spain)", ca: "Catalan", tzm_Latn: "Central Morocco Tamazight (Latin)", tzm_Latn_MA: "Central Morocco Tamazight (Latin, Morocco)", tzm: "Central Morocco Tamazight", da_DK: "Danish (Denmark)", da: "Danish", nl_BE: "Dutch (Belgium)", nl_NL: "Dutch (Netherlands)", nl: "Dutch", et_EE: "Estonian (Estonia)", et: "Estonian", fi_FI: "Finnish (Finland)", fi: "Finnish", fr_BE: "French (Belgium)", fr_BJ: "French (Benin)", fr_BF: "French (Burkina Faso)", fr_BI: "French (Burundi)", fr_CM: "French (Cameroon)", fr_CA: "French (Canada)", fr_CF: "French (Central African Republic)", fr_TD: "French (Chad)", fr_KM: "French (Comoros)", fr_CG: "French (Congo - Brazzaville)", fr_CD: "French (Congo - Kinshasa)", fr_CI: "French (Côte d’Ivoire)", fr_DJ: "French (Djibouti)", fr_GQ: "French (Equatorial Guinea)", fr_FR: "French (France)", fr_GA: "French (Gabon)", fr_GP: "French (Guadeloupe)", fr_GN: "French (Guinea)", fr_LU: "French (Luxembourg)", fr_MG: "French (Madagascar)", fr_ML: "French (Mali)", fr_MQ: "French (Martinique)", fr_MC: "French (Monaco)", fr_NE: "French (Niger)", fr_RW: "French (Rwanda)", fr_RE: "French (Réunion)", fr_BL: "French (Saint Barthélemy)", fr_MF: "French (Saint Martin)", fr_SN: "French (Senegal)", fr_CH: "French (Switzerland)", fr_TG: "French (Togo)", fr: "French", gl_ES: "Galician (Spain)", gl: "Galician", ka_GE: "Georgian (Georgia)", ka: "Georgian", de_AT: "German (Austria)", de_BE: "German (Belgium)", de_DE: "German (Germany)", de_LI: "German (Liechtenstein)", de_LU: "German (Luxembourg)", de_CH: "German (Switzerland)", de: "German", el_CY: "Greek (Cyprus)", el_GR: "Greek (Greece)", el: "Greek", hu_HU: "Hungarian (Hungary)", hu: "Hungarian", is_IS: "Icelandic (Iceland)", is: "Icelandic", id_ID: "Indonesian (Indonesia)", id: "Indonesian", it_IT: "Italian (Italy)", it_CH: "Italian (Switzerland)", it: "Italian", kab_DZ: "Kabyle (Algeria)", kab: "Kabyle", kl_GL: "Kalaallisut (Greenland)", kl: "Kalaallisut", lv_LV: "Latvian (Latvia)", lv: "Latvian", lt_LT: "Lithuanian (Lithuania)", lt: "Lithuanian", mk_MK: "Macedonian (Macedonia)", mk: "Macedonian", naq_NA: "Nama (Namibia)", naq: "Nama", pl_PL: "Polish (Poland)", pl: "Polish", pt_BR: "Portuguese (Brazil)", pt_GW: "Portuguese (Guinea-Bissau)", pt_MZ: "Portuguese (Mozambique)", pt_PT: "Portuguese (Portugal)", pt: "Portuguese", ro_MD: "Romanian (Moldova)", ro_RO: "Romanian (Romania)", ro: "Romanian", ru_MD: "Russian (Moldova)", ru_RU: "Russian (Russia)", ru_UA: "Russian (Ukraine)", ru: "Russian", seh_MZ: "Sena (Mozambique)", seh: "Sena", sk_SK: "Slovak (Slovakia)", sk: "Slovak", sl_SI: "Slovenian (Slovenia)", sl: "Slovenian", es_AR: "Spanish (Argentina)", es_BO: "Spanish (Bolivia)", es_CL: "Spanish (Chile)", es_CO: "Spanish (Colombia)", es_CR: "Spanish (Costa Rica)", es_DO: "Spanish (Dominican Republic)", es_EC: "Spanish (Ecuador)", es_SV: "Spanish (El Salvador)", es_GQ: "Spanish (Equatorial Guinea)", es_GT: "Spanish (Guatemala)", es_HN: "Spanish (Honduras)", es_419: "Spanish (Latin America)", es_MX: "Spanish (Mexico)", es_NI: "Spanish (Nicaragua)", es_PA: "Spanish (Panama)", es_PY: "Spanish (Paraguay)", es_PE: "Spanish (Peru)", es_PR: "Spanish (Puerto Rico)", es_ES: "Spanish (Spain)", es_US: "Spanish (United States)", es_UY: "Spanish (Uruguay)", es_VE: "Spanish (Venezuela)", es: "Spanish", sv_FI: "Swedish (Finland)", sv_SE: "Swedish (Sweden)", sv: "Swedish", tr_TR: "Turkish (Turkey)", tr: "Turkish", uk_UA: "Ukrainian (Ukraine)", uk: "Ukrainian", vi_VN: "Vietnamese (Vietnam)", vi: "Vietnamese" } var SS = SpreadsheetApp.getActiveSpreadsheet(); var LocalS = SS.getSpreadsheetLocale(); if (LANGUAGE_BY_LOCALE[LocalS] == undefined) { return false; } //Logger.log(true); return true; } /* function ReplaceDotsToCommas(dataIn) { var dataOut = dataIn.map(function(num) { if (isNaN(num)) { return num; } num = num.toString(); return num.replace(".", ","); }); return dataOut; } */ Here's set of variables that are to be changed, you'll find them in script: var TargetSheet = 'Main'; // name of sheet with data validation var LogSheet = 'Data2'; // name of sheet with data var NumOfLevels = 7; // number of levels of data validation var lcol = 9; // number of column where validation starts; A = 1, B = 2, etc. var lrow = 2; // number of row where validation starts var offsets = [1,1,1,1,1,1,1]; // offsets for levels I suggest everyone, who knows scripts well, send your edits to this code. I guess, there's simpler way to find validation list and make script run faster.
Here you have another solution based on the one provided by #tarheel function onEdit() { var sheetWithNestedSelectsName = "Sitemap"; var columnWithNestedSelectsRoot = 1; var sheetWithOptionPossibleValuesSuffix = "TabSections"; var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet(); var activeSheet = SpreadsheetApp.getActiveSheet(); // If we're not in the sheet with nested selects, exit! if ( activeSheet.getName() != sheetWithNestedSelectsName ) { return; } var activeCell = SpreadsheetApp.getActiveRange(); // If we're not in the root column or a content row, exit! if ( activeCell.getColumn() != columnWithNestedSelectsRoot || activeCell.getRow() < 2 ) { return; } var sheetWithActiveOptionPossibleValues = activeSpreadsheet.getSheetByName( activeCell.getValue() + sheetWithOptionPossibleValuesSuffix ); // Get all possible values var activeOptionPossibleValues = sheetWithActiveOptionPossibleValues.getSheetValues( 1, 1, -1, 1 ); var possibleValuesValidation = SpreadsheetApp.newDataValidation(); possibleValuesValidation.setAllowInvalid( false ); possibleValuesValidation.requireValueInList( activeOptionPossibleValues, true ); activeSheet.getRange( activeCell.getRow(), activeCell.getColumn() + 1 ).setDataValidation( possibleValuesValidation.build() ); } It has some benefits over the other approach: You don't need to edit the script every time you add a "root option". You only have to create a new sheet with the nested options of this root option. I've refactored the script providing more semantic names for the variables and so on. Furthermore, I've extracted some parameters to variables in order to make it easier to adapt to your specific case. You only have to set the first 3 values. There's no limit of nested option values (I've used the getSheetValues method with the -1 value). So, how to use it: Create the sheet where you'll have the nested selectors Go to the "Tools" > "Script Editor…" and select the "Blank project" option Paste the code attached to this answer Modify the first 3 variables of the script setting up your values and save it Create one sheet within this same document for each possible value of the "root selector". They must be named as the value + the specified suffix. Enjoy!
Edit: The answer below may be satisfactory, but it has some drawbacks: There is a noticeable pause for the running of the script. I'm on a 160 ms latency, and it's enough to be annoying. It works by building a new range each time you edit a given row. This gives an 'invalid contents' to previous entries some of the time I hope others can clean this up somewhat. Here's another way to do it, that saves you a ton of range naming: Three sheets in the worksheet: call them Main, List, and DRange (for dynamic range.) On the Main sheet, column 1 contains a timestamp. This time stamp is modified onEdit. On List your categories and subcategories are arranged as a simple list. I'm using this for plant inventory at my tree farm, so my list looks like this: Group | Genus | Bot_Name Conifer | Abies | Abies balsamea Conifer | Abies | Abies concolor Conifer | Abies | Abies lasiocarpa var bifolia Conifer | Pinus | Pinus ponderosa Conifer | Pinus | Pinus sylvestris Conifer | Pinus | Pinus banksiana Conifer | Pinus | Pinus cembra Conifer | Picea | Picea pungens Conifer | Picea | Picea glauca Deciduous | Acer | Acer ginnala Deciduous | Acer | Acer negundo Deciduous | Salix | Salix discolor Deciduous | Salix | Salix fragilis ... Where | indicates separation into columns. For convenience I also used the headers as names for named ranges. DRrange A1 has the formula =Max(Main!A2:A1000) This returns the most recent timestamp. A2 to A4 have variations on: =vlookup($A$1,Inventory!$A$1:$E$1000,2,False) with the 2 being incremented for each cell to the right. On running A2 to A4 will have the currently selected Group, Genus and Species. Below each of these, is a filter command something like this: =unique(filter(Bot_Name,REGEXMATCH(Bot_Name,C1))) These filters will populate a block below with matching entries to the contents of the top cell. The filters can be modified to suit your needs, and to the format of your list. Back to Main: Data validation in Main is done using ranges from DRange. The script I use: function onEdit(event) { //SETTINGS var dynamicSheet='DRange'; //sheet where the dynamic range lives var tsheet = 'Main'; //the sheet you are monitoring for edits var lcol = 2; //left-most column number you are monitoring; A=1, B=2 etc var rcol = 5; //right-most column number you are monitoring var tcol = 1; //column number in which you wish to populate the timestamp // var s = event.source.getActiveSheet(); var sname = s.getName(); if (sname == tsheet) { var r = event.source.getActiveRange(); var scol = r.getColumn(); //scol is the column number of the edited cell if (scol >= lcol && scol <= rcol) { s.getRange(r.getRow(), tcol).setValue(new Date()); for(var looper=scol+1; looper<=rcol; looper++) { s.getRange(r.getRow(),looper).setValue(""); //After edit clear the entries to the right } } } } Original Youtube presentation that gave me most of the onEdit timestamp component: https://www.youtube.com/watch?v=RDK8rjdE85Y
Continuing the evolution of this solution I've upped the ante by adding support for multiple root selections and deeper nested selections. This is a further development of JavierCane's solution (which in turn built on tarheel's). /** * "on edit" event handler * * Based on JavierCane's answer in * * http://stackoverflow.com/questions/21744547/how-do-you-do-dynamic-dependent-drop-downs-in-google-sheets * * Each set of options has it own sheet named after the option. The * values in this sheet are used to populate the drop-down. * * The top row is assumed to be a header. * * The sub-category column is assumed to be the next column to the right. * * If there are no sub-categories the next column along is cleared in * case the previous selection did have options. */ function onEdit() { var NESTED_SELECTS_SHEET_NAME = "Sitemap" var NESTED_SELECTS_ROOT_COLUMN = 1 var SUB_CATEGORY_COLUMN = NESTED_SELECTS_ROOT_COLUMN + 1 var NUMBER_OF_ROOT_OPTION_CELLS = 3 var OPTION_POSSIBLE_VALUES_SHEET_SUFFIX = "" var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet() var activeSheet = SpreadsheetApp.getActiveSheet() if (activeSheet.getName() !== NESTED_SELECTS_SHEET_NAME) { // Not in the sheet with nested selects, exit! return } var activeCell = SpreadsheetApp.getActiveRange() // Top row is the header if (activeCell.getColumn() > SUB_CATEGORY_COLUMN || activeCell.getRow() === 1 || activeCell.getRow() > NUMBER_OF_ROOT_OPTION_CELLS + 1) { // Out of selection range, exit! return } var sheetWithActiveOptionPossibleValues = activeSpreadsheet .getSheetByName(activeCell.getValue() + OPTION_POSSIBLE_VALUES_SHEET_SUFFIX) if (sheetWithActiveOptionPossibleValues === null) { // There are no further options for this value, so clear out any old // values activeSheet .getRange(activeCell.getRow(), activeCell.getColumn() + 1) .clearDataValidations() .clearContent() return } // Get all possible values var activeOptionPossibleValues = sheetWithActiveOptionPossibleValues .getSheetValues(1, 1, -1, 1) var possibleValuesValidation = SpreadsheetApp.newDataValidation() possibleValuesValidation.setAllowInvalid(false) possibleValuesValidation.requireValueInList(activeOptionPossibleValues, true) activeSheet .getRange(activeCell.getRow(), activeCell.getColumn() + 1) .setDataValidation(possibleValuesValidation.build()) } // onEdit() As Javier says: Create the sheet where you'll have the nested selectors Go to the "Tools" > "Script Editor…" and select the "Blank project" option Paste the code attached to this answer Modify the constants at the top of the script setting up your values and save it Create one sheet within this same document for each possible value of the "root selector". They must be named as the value + the specified suffix. And if you wanted to see it in action I've created a demo sheet and you can see the code if you take a copy.